Add a trace statement to be able to track down which implementation handles a MultiCommand

This commit is contained in:
Alex Dima 2021-03-23 12:55:13 +01:00
parent 9089e0cbd9
commit afca44535d
No known key found for this signature in database
GPG key ID: 6E58D7B045760DA0
10 changed files with 38 additions and 29 deletions

View file

@ -281,7 +281,7 @@ abstract class EditorOrNativeTextInputCommand {
constructor(target: MultiCommand) {
// 1. handle case when focus is in editor.
target.addImplementation(10000, (accessor: ServicesAccessor, args: any) => {
target.addImplementation(10000, 'code-editor', (accessor: ServicesAccessor, args: any) => {
// Only if editor text focus (i.e. not if editor has widget focus).
const focusedEditor = accessor.get(ICodeEditorService).getFocusedCodeEditor();
if (focusedEditor && focusedEditor.hasTextFocus()) {
@ -291,7 +291,7 @@ abstract class EditorOrNativeTextInputCommand {
});
// 2. handle case when focus is in some other `input` / `textarea`.
target.addImplementation(1000, (accessor: ServicesAccessor, args: any) => {
target.addImplementation(1000, 'generic-dom-input-textarea', (accessor: ServicesAccessor, args: any) => {
// Only if focused on an element that allows for entering text
const activeElement = <HTMLElement>document.activeElement;
if (activeElement && ['input', 'textarea'].indexOf(activeElement.tagName.toLowerCase()) >= 0) {
@ -302,7 +302,7 @@ abstract class EditorOrNativeTextInputCommand {
});
// 3. (default) handle case when focus is somewhere else.
target.addImplementation(0, (accessor: ServicesAccessor, args: any) => {
target.addImplementation(0, 'generic-dom', (accessor: ServicesAccessor, args: any) => {
// Redirecting to active editor
const activeEditor = accessor.get(ICodeEditorService).getActiveCodeEditor();
if (activeEditor) {

View file

@ -23,6 +23,7 @@ import { withNullAsUndefined, assertType } from 'vs/base/common/types';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { IDisposable } from 'vs/base/common/lifecycle';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { ILogService } from 'vs/platform/log/common/log';
export type ServicesAccessor = InstantiationServicesAccessor;
@ -149,20 +150,26 @@ export abstract class Command {
*/
export type CommandImplementation = (accessor: ServicesAccessor, args: unknown) => boolean | Promise<void>;
interface ICommandImplementationRegistration {
priority: number;
name: string;
implementation: CommandImplementation;
}
export class MultiCommand extends Command {
private readonly _implementations: [number, CommandImplementation][] = [];
private readonly _implementations: ICommandImplementationRegistration[] = [];
/**
* A higher priority gets to be looked at first
*/
public addImplementation(priority: number, implementation: CommandImplementation): IDisposable {
this._implementations.push([priority, implementation]);
this._implementations.sort((a, b) => b[0] - a[0]);
public addImplementation(priority: number, name: string, implementation: CommandImplementation): IDisposable {
this._implementations.push({ priority, name, implementation });
this._implementations.sort((a, b) => b.priority - a.priority);
return {
dispose: () => {
for (let i = 0; i < this._implementations.length; i++) {
if (this._implementations[i][1] === implementation) {
if (this._implementations[i].implementation === implementation) {
this._implementations.splice(i, 1);
return;
}
@ -172,9 +179,11 @@ export class MultiCommand extends Command {
}
public runCommand(accessor: ServicesAccessor, args: any): void | Promise<void> {
const logService = accessor.get(ILogService);
for (const impl of this._implementations) {
const result = impl[1](accessor, args);
const result = impl.implementation(accessor, args);
if (result) {
logService.trace(`Command '${this.id}' was handled by '${impl.name}'.`);
if (typeof result === 'boolean') {
return;
}

View file

@ -169,7 +169,7 @@ function registerExecCommandImpl(target: MultiCommand | undefined, browserComman
}
// 1. handle case when focus is in editor.
target.addImplementation(10000, (accessor: ServicesAccessor, args: any) => {
target.addImplementation(10000, 'code-editor', (accessor: ServicesAccessor, args: any) => {
// Only if editor text focus (i.e. not if editor has widget focus).
const focusedEditor = accessor.get(ICodeEditorService).getFocusedCodeEditor();
if (focusedEditor && focusedEditor.hasTextFocus()) {
@ -186,7 +186,7 @@ function registerExecCommandImpl(target: MultiCommand | undefined, browserComman
});
// 2. (default) handle case when focus is somewhere else.
target.addImplementation(0, (accessor: ServicesAccessor, args: any) => {
target.addImplementation(0, 'generic-dom', (accessor: ServicesAccessor, args: any) => {
document.execCommand(browserCommand);
return true;
});
@ -197,7 +197,7 @@ registerExecCommandImpl(CopyAction, 'copy');
if (PasteAction) {
// 1. Paste: handle case when focus is in editor.
PasteAction.addImplementation(10000, (accessor: ServicesAccessor, args: any) => {
PasteAction.addImplementation(10000, 'code-editor', (accessor: ServicesAccessor, args: any) => {
const codeEditorService = accessor.get(ICodeEditorService);
const clipboardService = accessor.get(IClipboardService);
@ -235,7 +235,7 @@ if (PasteAction) {
});
// 2. Paste: (default) handle case when focus is somewhere else.
PasteAction.addImplementation(0, (accessor: ServicesAccessor, args: any) => {
PasteAction.addImplementation(0, 'generic-dom', (accessor: ServicesAccessor, args: any) => {
document.execCommand('paste');
return true;
});

View file

@ -83,10 +83,10 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
}));
const PRIORITY = 105;
this._register(UndoCommand.addImplementation(PRIORITY, () => {
this._register(UndoCommand.addImplementation(PRIORITY, 'custom-editor', () => {
return this.withActiveCustomEditor(editor => editor.undo());
}));
this._register(RedoCommand.addImplementation(PRIORITY, () => {
this._register(RedoCommand.addImplementation(PRIORITY, 'custom-editor', () => {
return this.withActiveCustomEditor(editor => editor.redo());
}));

View file

@ -286,7 +286,7 @@ CommandsRegistry.registerCommand({
});
function overrideActionForActiveExtensionEditorWebview(command: MultiCommand | undefined, f: (webview: Webview) => void) {
command?.addImplementation(105, (accessor) => {
command?.addImplementation(105, 'extensions-editor', (accessor) => {
const editorService = accessor.get(IEditorService);
const editor = editorService.activeEditorPane;
if (editor instanceof ExtensionEditor) {

View file

@ -389,7 +389,7 @@ configurationRegistry.registerConfiguration({
}
});
UndoCommand.addImplementation(110, (accessor: ServicesAccessor) => {
UndoCommand.addImplementation(110, 'explorer', (accessor: ServicesAccessor) => {
const undoRedoService = accessor.get(IUndoRedoService);
const explorerService = accessor.get(IExplorerService);
if (explorerService.hasViewFocus() && undoRedoService.canUndo(UNDO_REDO_SOURCE)) {
@ -400,7 +400,7 @@ UndoCommand.addImplementation(110, (accessor: ServicesAccessor) => {
return false;
});
RedoCommand.addImplementation(110, (accessor: ServicesAccessor) => {
RedoCommand.addImplementation(110, 'explorer', (accessor: ServicesAccessor) => {
const undoRedoService = accessor.get(IUndoRedoService);
const explorerService = accessor.get(IExplorerService);
if (explorerService.hasViewFocus() && undoRedoService.canRedo(UNDO_REDO_SOURCE)) {

View file

@ -43,7 +43,7 @@ class NotebookClipboardContribution extends Disposable {
const PRIORITY = 105;
if (CopyAction) {
this._register(CopyAction.addImplementation(PRIORITY, accessor => {
this._register(CopyAction.addImplementation(PRIORITY, 'notebook-clipboard', accessor => {
const activeElement = <HTMLElement>document.activeElement;
if (activeElement && ['input', 'textarea'].indexOf(activeElement.tagName.toLowerCase()) >= 0) {
return false;
@ -80,7 +80,7 @@ class NotebookClipboardContribution extends Disposable {
}
if (PasteAction) {
PasteAction.addImplementation(PRIORITY, accessor => {
PasteAction.addImplementation(PRIORITY, 'notebook-clipboard', accessor => {
const activeElement = <HTMLElement>document.activeElement;
if (activeElement && ['input', 'textarea'].indexOf(activeElement.tagName.toLowerCase()) >= 0) {
return false;
@ -137,7 +137,7 @@ class NotebookClipboardContribution extends Disposable {
}
if (CutAction) {
CutAction.addImplementation(PRIORITY, accessor => {
CutAction.addImplementation(PRIORITY, 'notebook-clipboard', accessor => {
const activeElement = <HTMLElement>document.activeElement;
if (activeElement && ['input', 'textarea'].indexOf(activeElement.tagName.toLowerCase()) >= 0) {
return false;

View file

@ -18,7 +18,7 @@ class NotebookUndoRedoContribution extends Disposable {
super();
const PRIORITY = 105;
this._register(UndoCommand.addImplementation(PRIORITY, () => {
this._register(UndoCommand.addImplementation(PRIORITY, 'notebook-undo-redo', () => {
const editor = getNotebookEditorFromEditorPane(this._editorService.activeEditorPane);
if (editor?.viewModel) {
return editor.viewModel.undo().then(cellResources => {
@ -37,7 +37,7 @@ class NotebookUndoRedoContribution extends Disposable {
return false;
}));
this._register(RedoCommand.addImplementation(PRIORITY, () => {
this._register(RedoCommand.addImplementation(PRIORITY, 'notebook-undo-redo', () => {
const editor = getNotebookEditorFromEditorPane(this._editorService.activeEditorPane);
if (editor?.viewModel) {
return editor.viewModel.redo().then(cellResources => {

View file

@ -39,23 +39,23 @@ function withWebview(accessor: ServicesAccessor, f: (webviewe: ElectronWebviewBa
const PRIORITY = 105;
UndoCommand.addImplementation(PRIORITY, accessor => {
UndoCommand.addImplementation(PRIORITY, 'notebook-webview', accessor => {
return withWebview(accessor, webview => webview.undo());
});
RedoCommand.addImplementation(PRIORITY, accessor => {
RedoCommand.addImplementation(PRIORITY, 'notebook-webview', accessor => {
return withWebview(accessor, webview => webview.redo());
});
CopyAction?.addImplementation(PRIORITY, accessor => {
CopyAction?.addImplementation(PRIORITY, 'notebook-webview', accessor => {
return withWebview(accessor, webview => webview.copy());
});
PasteAction?.addImplementation(PRIORITY, accessor => {
PasteAction?.addImplementation(PRIORITY, 'notebook-webview', accessor => {
return withWebview(accessor, webview => webview.paste());
});
CutAction?.addImplementation(PRIORITY, accessor => {
CutAction?.addImplementation(PRIORITY, 'notebook-webview', accessor => {
return withWebview(accessor, webview => webview.cut());
});

View file

@ -11,7 +11,7 @@ import { IWebviewService, Webview } from 'vs/workbench/contrib/webview/browser/w
const PRIORITY = 100;
function overrideCommandForWebview(command: MultiCommand | undefined, f: (webview: Webview) => void) {
command?.addImplementation(PRIORITY, accessor => {
command?.addImplementation(PRIORITY, 'webiew', accessor => {
const webviewService = accessor.get(IWebviewService);
const webview = webviewService.activeWebview;
if (webview?.isFocused) {