ADR: User Script Debugging Support Architecture¶
Status¶
Accepted - Implemented across multiple PRs and ongoing enhancements
Date¶
2025-09-27
Context¶
OmegaT supports user scripts written in Groovy and JavaScript that are executed via javax.script.ScriptEngine.
These scripts have access to OmegaT’s core APIs through exposed bindings (project, editor, glossary, mainWindow, Core).
Currently, script developers face significant challenges in debugging their scripts:
No integrated debugging capabilities: Scripts must be debugged through print statements or external logging
Limited development environment support: While OmegaT provides a basic integrated editor with syntax highlighting, there is no code completion for OmegaT-specific APIs, no variable inspection, and no breakpoint debugging
No variable inspection: No way to inspect script variables or OmegaT object states during execution
Difficult error diagnosis: Stack traces from ScriptEngine don’t provide clear mapping to original source lines
Limited IDE integration: Developers who prefer external IDEs lack debugging support and OmegaT API intellisense
The community has expressed strong interest in modern debugging capabilities to improve script development productivity and attract more developers to the OmegaT scripting ecosystem.
Decision¶
We will implement script debugging support through the following architectural approach:
1. Refactor ScriptRunner Architecture¶
Extract AbstractScriptRunner: Create an abstract base class containing common functionality and template methods
Implement StandardScriptRunner: Maintain existing behavior with zero performance overhead
Implement DebugScriptRunner: Add debugging capabilities through script instrumentation and debug server
Maintain ScriptRunner as Facade: Ensure backward compatibility by delegating to AbstractScriptRunner
2. Debug Server Integration¶
HTTP-based Debug Server: Implement a lightweight HTTP server using Java’s built-in
HttpServerDebug Adapter Protocol Compatibility: Provide endpoints compatible with Debug Adapter Protocol(DAP)
Runtime Selection: Choose runner implementation based on system property
omegat.debug.scripts
3. Script Instrumentation Approach¶
Non-invasive Instrumentation: Inject debug tracking code without modifying the original script logic
Line Tracking: Add line number tracking for breakpoint support
Variable Watching: Provide debug helpers accessible to scripts via bindings
Breakpoint Support: Allow manual breakpoints through
breakpoint()function calls
4. External IDE/Editor Integration¶
Debug Configuration: Provide launch configurations for attaching to OmegaT debug sessions
Developer Documentation: Provide detailed documentation for script debugging
Implementation Details¶
Core Architecture¶
// Template method pattern
public abstract class AbstractScriptRunner {
public static Object executeScript(String script, ScriptEngine engine, Map<String, Object> additionalBindings) {
return getActiveRunner().doExecuteScript(script, engine, additionalBindings);
}
protected abstract Object doExecuteScript(String script, ScriptEngine engine, Map<String, Object> additionalBindings);
}
// Runtime selection
public static AbstractScriptRunner getActiveRunner() {
if (Boolean.getBoolean("omegat.debug.scripts")) {
return new DebugScriptRunner();
} else {
return new StandardScriptRunner();
}
}
Debug Server¶
Port: Default 8000, configurable via
omegat.debug.scripts.portEndpoints:
/setBreakpoints,/getVariables,/continue,/stepOverCommunication: JSON over HTTP, compatible with Debug Adapter Protocol
Security: Localhost-only binding for security
Script Instrumentation¶
Line Tracking: Inject
__debug__.trackLine(lineNumber)before executable statementsVariable Access: Provide
__debug__.watch(name, value)for variable inspectionManual Breakpoints: Global
breakpoint()function for explicit pause pointsConditional: Only active when the debug server is running
Consequences¶
Positive¶
Improved Developer Experience: Modern debugging capabilities comparable to professional IDEs
Backward Compatibility: Existing scripts and OmegaT installations remain unaffected
Performance: Zero overhead in standard mode; debug overhead only when explicitly enabled
Extensibility: Architecture supports future debugging enhancements
Community Growth: Lower barrier to entry for script development
External Tool Support: Enables integration with popular development environments
Negative¶
Increased Complexity: Additional code paths and components to maintain
Debugging Overhead: Performance impact when debug mode is enabled
Network Dependency: Debug server requires localhost network access
Maintenance Burden: Additional documentation, testing, and support requirements
Neutral¶
Optional Feature: Debug capabilities are opt-in and don’t affect standard usage
Standard Technologies: Uses well-established protocols (HTTP, Debug Adapter Protocol)
Incremental Implementation: Can be developed and deployed in phases
Alternatives Considered¶
1. Direct JVM Debugging¶
Approach: Use standard JVM debugging (-agentlib:jdwp) to debug scripts Rejected: ScriptEngine execution context makes this impractical; scripts run in a separate execution context
2. Custom Language Server¶
Approach: Implement Language Server Protocol for OmegaT scripts Rejected: Unnecessary complexity; existing Groovy/JavaScript language servers provide sufficient functionality
3. Plugin-based Debugging¶
Approach: Implement debugging entirely as an external plugin without core changes Rejected: Limited access to script execution context; would require reflection hacks
4. IDE-specific Integration¶
Approach: Integrate directly with specific IDEs (IntelliJ, Eclipse, VSCode) Rejected: Would limit accessibility. DAP’s universal protocol support can work across VSCode, Emacs, Vim/Neovim, Sublime Text, and numerous other editors without requiring separate integrations.
Implementation Plan¶
Phase 1: Core Refactoring¶
Extract AbstractScriptRunner with template methods
Implement StandardScriptRunner maintaining existing behavior
Update ScriptRunner facade for backward compatibility
Comprehensive testing to ensure no regressions
Phase 2: Debug Infrastructure¶
Implement DebugScriptRunner with instrumentation
Develop HTTP debug server with basic protocol support
Add debug helper bindings for scripts
Integration testing with sample scripts
Phase 3: IDE Integration¶
Implement OmegaT API type generation from Maven artifacts
Create debugging documentation and tutorials
Beta testing with community developers
Phase 4: Polish and Documentation¶
Performance optimization and stability improvements
Comprehensive documentation for developers and users
Community feedback integration
Release preparation
References¶
Phase 1: Refactoring¶
Phase 2: Debug Infrastructure¶
Appendix: Technical Specifications¶
System Properties¶
omegat.debug.scripts: Enable debug mode (boolean, default: false)omegat.debug.scripts.port: Debug server port (integer, default: 8000)
Script Debug API¶
// Available in debug mode
breakpoint() // Pause execution
__debug__.watch("variable", value) // Watch variable
__debug__.log("message") // Debug logging
__debug__.trackLine(lineNumber) // Internal line tracking
This ADR establishes the foundation for professional script debugging capabilities in OmegaT while maintaining the project’s commitment to backward compatibility and architectural integrity.