Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/contrib/codeAction/browser/codeActionKeybindingResolver.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { HierarchicalKind } from '../../../../base/common/hierarchicalKind.js';
7
import { ResolvedKeybinding } from '../../../../base/common/keybindings.js';
8
import { Lazy } from '../../../../base/common/lazy.js';
9
import { CodeAction } from '../../../common/languages.js';
10
import { codeActionCommandId, fixAllCommandId, organizeImportsCommandId, refactorCommandId, sourceActionCommandId } from './codeAction.js';
11
import { CodeActionAutoApply, CodeActionCommandArgs, CodeActionKind } from '../common/types.js';
12
import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.js';
13
14
interface ResolveCodeActionKeybinding {
15
readonly kind: HierarchicalKind;
16
readonly preferred: boolean;
17
readonly resolvedKeybinding: ResolvedKeybinding;
18
}
19
20
export class CodeActionKeybindingResolver {
21
private static readonly codeActionCommands: readonly string[] = [
22
refactorCommandId,
23
codeActionCommandId,
24
sourceActionCommandId,
25
organizeImportsCommandId,
26
fixAllCommandId
27
];
28
29
constructor(
30
@IKeybindingService private readonly keybindingService: IKeybindingService
31
) { }
32
33
public getResolver(): (action: CodeAction) => ResolvedKeybinding | undefined {
34
// Lazy since we may not actually ever read the value
35
const allCodeActionBindings = new Lazy<readonly ResolveCodeActionKeybinding[]>(() => this.keybindingService.getKeybindings()
36
.filter(item => CodeActionKeybindingResolver.codeActionCommands.indexOf(item.command!) >= 0)
37
.filter(item => item.resolvedKeybinding)
38
.map((item): ResolveCodeActionKeybinding => {
39
// Special case these commands since they come built-in with VS Code and don't use 'commandArgs'
40
let commandArgs = item.commandArgs;
41
if (item.command === organizeImportsCommandId) {
42
commandArgs = { kind: CodeActionKind.SourceOrganizeImports.value };
43
} else if (item.command === fixAllCommandId) {
44
commandArgs = { kind: CodeActionKind.SourceFixAll.value };
45
}
46
47
return {
48
resolvedKeybinding: item.resolvedKeybinding!,
49
...CodeActionCommandArgs.fromUser(commandArgs, {
50
kind: HierarchicalKind.None,
51
apply: CodeActionAutoApply.Never
52
})
53
};
54
}));
55
56
return (action) => {
57
if (action.kind) {
58
const binding = this.bestKeybindingForCodeAction(action, allCodeActionBindings.value);
59
return binding?.resolvedKeybinding;
60
}
61
return undefined;
62
};
63
}
64
65
private bestKeybindingForCodeAction(
66
action: CodeAction,
67
candidates: readonly ResolveCodeActionKeybinding[]
68
): ResolveCodeActionKeybinding | undefined {
69
if (!action.kind) {
70
return undefined;
71
}
72
const kind = new HierarchicalKind(action.kind);
73
74
return candidates
75
.filter(candidate => candidate.kind.contains(kind))
76
.filter(candidate => {
77
if (candidate.preferred) {
78
// If the candidate keybinding only applies to preferred actions, the this action must also be preferred
79
return action.isPreferred;
80
}
81
return true;
82
})
83
.reduceRight((currentBest, candidate) => {
84
if (!currentBest) {
85
return candidate;
86
}
87
// Select the more specific binding
88
return currentBest.kind.contains(candidate.kind) ? candidate : currentBest;
89
}, undefined as ResolveCodeActionKeybinding | undefined);
90
}
91
}
92
93