feat(testing): check that a contributed keybinding binds a declared command - #71
Merged
Merged
Conversation
…ommand VS Code validates the shape of a `contributes.keybindings` entry and never its command. `isValidContributedKeyBinding` checks types only; a keybinding naming a command nothing registers is accepted, given a weight, and does nothing at all when the key is pressed. Renaming or deleting a command and missing the manifest therefore leaves a shortcut that fails in silence, with no warning from the editor and nothing in a test suite to catch it. `DeclaredContributions` gains an optional `keybindings` field. Passing it checks that every entry binds a command the extension declares; its `allow` list names the built-in ids it may bind as well, because putting a key on a built-in is a supported use of the point and would otherwise fail the check. Omitting the field checks no keybindings, so every existing caller is unaffected. Both extensions this was trialled against had already hand-written a check here, which is the argument for having one: quick-utils asserts that every bound command is declared -- the same comparison -- and ClipShot pins the order of a pair of entries, which this deliberately does not do. Of a keybinding this reads the command id and nothing else. The key, `when` and `args` stay the manifest's, and so does the order, which is what decides the winner when several entries share a key. Verified against both consumers' real manifests: neither reports anything as it stands, a typo in a bound command is caught in each, and a built-in is reported without `allow` and accepted with it. Each of the five new assertions that could fail was run against the previous source first, and all five did. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
VS Code validates the shape of a
contributes.keybindingsentry and never itscommand.
isValidContributedKeyBindingchecks types only — a keybinding naming acommand nothing registers is accepted, given a weight, and does nothing at all when the
key is pressed. Renaming or deleting a command and missing the manifest leaves a shortcut
that fails in silence, with no warning from the editor and nothing in a test suite to
catch it.
What this adds
DeclaredContributionsgains an optionalkeybindingsfield:Passing it checks that every entry binds a command the extension declares.
allownamesthe built-in ids it may bind as well, because putting a key on a built-in is a supported
use of the contribution point and would otherwise fail the check.
Omitting the field checks no keybindings, so every existing caller is unaffected.
ManifestMismatch['kind']gains'keybinding'; a caller switching exhaustively over itneeds the new case.
Why the library and not each extension
Both extensions this was trialled against had already hand-written a check here:
Of a keybinding this reads the command id and nothing else. The key,
whenandargsstay the manifest's, and so does the order — so an extension that leans on it still needs
an assertion of its own, and ClipShot's is the worked example.
Verified
Trialled against both consumers' real
package.json:npm run quality: 1094 tests, all green (7 new)npm run verify:package: all package checks passedfirst, and all five did. The remaining two — the passing case and the opt-out — pass
on both sides by their nature
The VS Code behaviour above was read from
release/1.137(
keybindingService.ts,keybindingsRegistry.ts,keybindingResolver.ts), not inferred.🤖 Generated with Claude Code