Phase 3 successfully implemented "Configuration-Based AI, Action Registration and Shortcuts" functionality, enabling the plugin to dynamically register actions, shortcuts, and context menus based on configuration, supporting configuration persistence and dynamic updates. Through architectural optimization, better code reuse and logic simplification were achieved.
File: src/main/kotlin/com/github/switch2ai/actions/AbstractDynamicActionRegistry.kt
Functionality:
- Provides common logic for dynamic action registration
- Supports shortcut registration, conflict detection, action management, etc.
- Uses generic design to support different types of configuration data
- Implements code reuse and logic simplification
Core Features:
- Generic Design: Uses generic
Tto support different types of configuration data - Common Logic: Contains common functionality like shortcut registration, conflict detection, action management
- Abstract Interface: Defines interfaces that subclasses must implement, ensuring consistency
- Code Reuse: Eliminates duplicate code, improves maintainability
File: src/main/kotlin/com/github/switch2ai/actions/DynamicActionRegistry.kt
Functionality:
- Inherits from
AbstractDynamicActionRegistry, focusing on action registration - Dynamically creates and registers actions based on configuration
- Automatically registers shortcut bindings
- Adds actions to editor context menu
Core Features:
- Inheritance Architecture: Inherits from abstract parent class, reusing common logic
- Code Simplification: Reduced from 380 lines to about 200 lines
- Clear Responsibilities: Focuses on action registration and context menu management
- Configuration Driven: Gets configuration from
AppSettingsState
File: src/main/kotlin/com/github/switch2ai/actions/DynamicSwitchAIActionRegistry.kt
Functionality:
- Inherits from
AbstractDynamicActionRegistry, focusing on AI switch actions - Dynamically creates AI switch actions based on configuration
- Supports AI switch shortcut registration
- Integrates with
AIStatusBarWidget
Core Features:
- Inheritance Architecture: Inherits from abstract parent class, reusing common logic
- Code Simplification: Reduced from 236 lines to about 100 lines
- AI Switching: Supports dynamic AI switch action registration
- State Synchronization: Maintains synchronization with status bar components
File: src/main/kotlin/com/github/switch2ai/settings/AppSettingsState.kt
Functionality:
- Merged original
ConfigurationManagerfunctionality - Manages AI list and action configuration
- Provides configuration persistence and dynamic updates
- Supports configuration change listening and restart detection
Core Features:
- Unified Management: All configuration logic centralized in one place
- Data Class Merging: Uses unified
AIConfigDataandActionConfigData - Persistence: Leverages IntelliJ's
PersistentStateComponentmechanism - Configuration Synchronization: Supports real-time configuration updates and synchronization
Through abstract parent classes and unified configuration management, better code reuse and logic simplification were achieved:
AbstractDynamicActionRegistry<T>
↓ ↓
DynamicActionRegistry DynamicSwitchAIActionRegistry
↓ ↓
ActionManager AIStatusBarWidget
AppSettingsState (Unified Configuration Management)
↓
PersistentStateComponent (Persistence)
↓
DynamicActionRegistry + DynamicSwitchAIActionRegistry
AppSettingsState (Unified Configuration Source)
↓
AbstractDynamicActionRegistry (Abstract Parent Class)
↓ ↓
DynamicActionRegistry DynamicSwitchAIActionRegistry
↓ ↓
ActionManager AIStatusBarWidget
Through AppSettingsState, all configurations are unified managed, achieving better data consistency and maintainability:
data class PluginConfig(
val aiList: Map<String, AIConfigData>, // AI configuration list
val actions: Map<String, ActionConfigData> // Action configuration list
)
data class AIConfigData(
var name: String = "", // AI name
var shortcut: String = "" // AI switch shortcut
)
data class ActionConfigData(
var name: String = "", // Action name
var description: String = "", // Action description
var shortCut: String = "", // Action shortcut
var commands: MutableMap<String, String> = mutableMapOf() // AI command mapping
)- Unified Types: Uses one set of mutable data classes, avoiding duplicate definitions
- Simplified Conversion: No type conversion needed, directly uses unified data types
- Performance Improvement: Avoids unnecessary object creation and copying
- Uses IntelliJ's
PersistentStateComponentinterface - Automatically saves to
switch2aiSettings.xmlfile - Supports hot updates and cold start of configuration
- Automatically synchronizes configuration changes to all related components
option+shift+o: Open file in AIoption+shift+t: Generate unit testsoption+shift+1/2/3: Switch AI
- Editor Context Menu: Right-click in code editor
- Project View Context Menu: Right-click in project file tree
- Tools Menu: In main menu bar tools menu
- Automatically generates menu items based on configuration
- Supports separators and grouping
- Automatically updates menu state
// Get unified configuration manager
val appSettings = AppSettingsState.getInstance()
// Get current configuration
val currentConfig = appSettings.getCurrentConfig()
// Update configuration
val newConfig = createNewConfig()
appSettings.updateConfig(newConfig, project)
// Listen for configuration changes
appSettings.addConfigChangeListener { newConfig ->
println("Configuration updated: $newConfig")
}// Get dynamic registry
val dynamicRegistry = DynamicActionRegistry.getInstance(project)
// Register all actions (automatically gets configuration from AppSettingsState)
dynamicRegistry.registerAllActions(project, appSettings.getCurrentConfig())
// Get AI switch registry
val aiSwitchRegistry = DynamicSwitchAIActionRegistry.getInstance(project)
// Register AI switch actions
aiSwitchRegistry.registerAllActions(project, appSettings.getCurrentConfig())// Create custom dynamic registry
class CustomActionRegistry : AbstractDynamicActionRegistry<CustomConfig>() {
override fun getCurrentConfig(): Map<String, CustomConfig>? = currentConfig
override fun setCurrentConfig(config: Map<String, CustomConfig>) { currentConfig = config }
override fun isConfigSame(newConfig: Map<String, CustomConfig>): Boolean = /* implementation logic */
override fun deepCopyConfig(config: Map<String, CustomConfig>): Map<String, CustomConfig> = /* implementation logic */
override fun registerAction(project: Project, key: String, config: CustomConfig) { /* implementation logic */ }
override fun getActionIdPrefix(): String = "custom."
}- Comprehensive try-catch blocks
- Detailed error logging
- User-friendly error prompts
- Uses default configuration when configuration loading fails
- Graceful degradation when action registration fails
According to project planning, next steps could include:
- YAML Configuration Support: Implement complete YAML configuration file loading
- Configuration Import/Export: Support configuration backup and restoration
- User Interface Optimization: Improve configuration interface user experience
- Performance Monitoring: Add performance metrics and monitoring
Phase 3 successfully implemented a configuration-based dynamic action registration and shortcut binding system. Through architectural optimization, better code reuse and logic simplification were achieved, giving the plugin:
- Code Reuse: Reduced about 300 lines of duplicate code through abstract parent classes
- Logic Unification: All dynamic registries use the same core logic
- Maintenance Simplification: Common logic modifications only need to be made in parent classes
- Extension Convenience: Adding new registries becomes very simple
- High Configurability: Supports flexible configuration definitions
- Dynamic Update Capability: Configuration changes can take effect in real-time
- User Friendliness: Clear prompts and error handling
- System Integration: Deep integration with IntelliJ platform
- Configuration Synchronization: All components automatically synchronize configuration changes
- Abstract Inheritance: Uses generic abstract parent classes for code reuse
- Unified Configuration: Unified management of all configurations through
AppSettingsState - Data Class Merging: Uses unified data types to avoid duplicate definitions
- Automatic Synchronization: Automatically synchronizes configuration changes to all related components
These features provide a solid foundation for the plugin's subsequent extension and maintenance, enabling the plugin to better adapt to different user needs and system environments. Through architectural optimization, code quality has been significantly improved, providing a good foundation for future functionality extensions.