What are Contributions?
A workbench contribution is a class that:- Implements
IWorkbenchContributioninterface - Is instantiated at a specific lifecycle phase
- Uses dependency injection to access services
- Registers functionality like commands, views, or event handlers
- Is automatically disposed when the workbench shuts down
Contributions are similar to extension activation, but they run in the core workbench process and have access to internal APIs.
Contribution Types
1. Phase-Based Contributions
Most contributions are loaded at a specific lifecycle phase:2. Lazy Contributions
Contributions that load only when explicitly requested:3. Editor-Specific Contributions
Contributions that load when a specific editor type is opened:Creating a Contribution
Basic Contribution
Registering a Contribution
Use the newregisterWorkbenchContribution2 API:
Always provide a unique ID for contributions to enable tracking and debugging.
Real-World Examples
Example 1: Debug Contribution
From the Debug feature:- Eventually: Status and progress indicators (non-critical)
- Restored: Debug toolbar (visible immediately)
- AfterRestored: Chat integration (after UI is ready)
Example 2: View Container Registration
Registering a custom view container:Example 3: Command Registration
Registering commands in a contribution:Contribution Patterns
Pattern 1: Event Handler Contribution
React to workbench events:Pattern 2: Configuration Listener
Respond to configuration changes:Pattern 3: Lifecycle-Aware Contribution
Perform actions at specific lifecycle events:Choosing the Right Phase
Phase Selection Guidelines
Phase Selection Guidelines
BlockStartup
Use when:- Absolutely critical for workbench initialization
- Must run before any UI is shown
- Very rare - avoid if possible
BlockRestore
Use when:- Required for UI restoration
- Must run before editors are shown
- Still blocks UI - use sparingly
AfterRestored (Recommended)
Use when:- Most feature contributions
- Can wait until UI is visible
- Doesn’t impact initial load time
Eventually
Use when:- Non-critical features
- Can load in background
- Doesn’t affect user experience if delayed
Lazy Contributions
For features that should only load when needed:Editor-Specific Contributions
Load contributions only when specific editor types open:Best Practices
Contribution Best Practices
Contribution Best Practices
- Choose the Right Phase: Use
AfterRestoredorEventuallyunless you have a specific reason - Keep Constructors Light: Move heavy initialization to async methods
- Dispose Properly: Always extend
Disposableand use_register() - Use Unique IDs: Provide descriptive, unique IDs for all contributions
- Avoid Side Effects: Don’t perform actions that modify global state in constructor
- Lazy Load When Possible: Use lazy contributions for optional features
- Handle Errors Gracefully: Wrap initialization in try-catch to avoid breaking workbench
- Document Dependencies: Clearly document which services your contribution requires
Debugging Contributions
VS Code provides tools to debug contribution loading:Migration from Old API
If you’re using the deprecated API:Next Steps
Views and Panels
Learn how to create custom views in contributions
Commands and Menus
Register commands and menu items in contributions