Expand description
Debug Adapter Protocol Implementation for Perl
This crate provides a production-grade Debug Adapter Protocol (DAP) server for Perl, enabling debugging support in VSCode, Neovim, Emacs, and other DAP-compatible editors.
The adapter integrates with perl_parser for AST-based breakpoint validation and
leverages existing LSP infrastructure for position mapping and workspace navigation.
§Features
- Native Runtime: Current launch/attach implementation for Perl debugging sessions
- Launch Debugging: Start and debug Perl processes with full control
- Attach Debugging: Attach to running Perl processes via TCP
- Legacy Bridge Mode: Compatibility proxy for Perl::LanguageServer installations
- AST-Based Validation: Breakpoint validation using parsed syntax trees
- Cross-Platform: Windows, macOS, and Linux support with path normalization
- Configuration Snippets: VSCode launch.json generation
§Quick Start
§Native and Bridge Modes
Native launch and attach are the current default runtime paths for new sessions. The legacy bridge adapter remains available when an installation still needs to proxy DAP messages to Perl::LanguageServer:
use perl_dap::BridgeAdapter;
let mut adapter = BridgeAdapter::new();
// Start Perl::LanguageServer DAP backend
adapter.spawn_pls_dap().await?;
// Proxy messages between VSCode and PLS
adapter.proxy_messages().await?;
// Cleanup on shutdown
adapter.shutdown().await?;§Launch Configuration
Create debugging configurations for launching Perl scripts:
use perl_dap::LaunchConfiguration;
use std::path::PathBuf;
use std::collections::HashMap;
let config = LaunchConfiguration {
program: PathBuf::from("script.pl"),
args: vec!["--verbose".to_string()],
cwd: Some(PathBuf::from("/workspace")),
env: HashMap::new(),
perl_path: None,
include_paths: vec![PathBuf::from("lib")],
};
// Validate configuration before launching
config.validate()?;§Attach Configuration
Attach to running Perl processes via TCP:
use perl_dap::AttachConfiguration;
let config = AttachConfiguration {
host: "localhost".to_string(),
port: 13603,
timeout_ms: Some(5000),
stop_on_entry: None,
};
config.validate()?;§VSCode Integration
Generate launch.json snippets for VSCode:
use perl_dap::{create_launch_json_snippet, create_attach_json_snippet};
// Generate launch configuration snippet
let launch_snippet = create_launch_json_snippet();
println!("{}", launch_snippet);
// Generate attach configuration snippet
let attach_snippet = create_attach_json_snippet();
println!("{}", attach_snippet);§Architecture
perl-dap exposes a dual architecture that supports both current runtime use
and compatibility migration:
- Native runtime (
DapServer+DebugAdapter) handles launch/attach flows, request dispatch, breakpoint/state management, and variable/evaluate inspection paths. - Legacy bridge (
BridgeAdapter) proxies traffic toPerl::LanguageServerfor compatibility when teams are still migrating. - Shared foundations (
protocol,dispatcher,breakpoints,platform) provide message contracts, routing, validation, and cross-platform process setup.
This keeps one crate boundary for editor integrations while allowing per-session selection between native execution and bridge fallback behavior.
§Protocol Support
The adapter implements DAP 1.51+ specification features:
§Initialization
initialize- Capability negotiationattach/launch- Debug session startconfigurationDone- Initialization completedisconnect- Session termination
§Breakpoints
setBreakpoints- Set breakpoints with AST validationsetFunctionBreakpoints- Break on function entrysetExceptionBreakpoints- Break on exceptions
§Execution Control
continue- Resume executionnext- Step overstepIn- Step intostepOut- Step outpause- Pause execution
§Inspection
threads- List active threadsstackTrace- Get call stackscopes- Get variable scopesvariables- Inspect variables with lazy loadingevaluate- Evaluate expressions in context
§Breakpoint Validation
The breakpoints module provides AST-based validation:
use perl_dap::{BreakpointStore, SourceBreakpoint};
use perl_parser::Parser;
let code = "sub foo {\n my $x = 1;\n return $x;\n}";
let mut parser = Parser::new(code);
let ast = parser.parse()?;
let mut store = BreakpointStore::new();
let bp = SourceBreakpoint {
line: 2,
column: None,
condition: None,
hit_condition: None,
log_message: None,
};
// Validate breakpoint is on executable line
let validated = store.add_breakpoint("script.pl", bp, &ast);§Platform Support
The platform module handles cross-platform concerns:
- Path Resolution: Normalize paths for Windows/Unix
- Perl Discovery: Find Perl interpreter in PATH
- Environment Setup: Configure @INC and environment variables
- Process Spawning: Launch Perl processes with proper stdio handling
use perl_dap::platform::{find_perl, normalize_path};
let perl = find_perl().unwrap_or_else(|| std::path::PathBuf::from("/usr/bin/perl"));
let normalized = normalize_path("/workspace/lib/Foo.pm");§Configuration Examples
§VSCode launch.json
{
"version": "0.2.0",
"configurations": [
{
"type": "perl",
"request": "launch",
"name": "Debug Perl Script",
"program": "${workspaceFolder}/script.pl",
"args": ["--verbose"],
"cwd": "${workspaceFolder}",
"includePaths": ["lib", "local/lib/perl5"]
},
{
"type": "perl",
"request": "attach",
"name": "Attach to Perl",
"host": "localhost",
"port": 13603
}
]
}§Programmatic Configuration
use perl_dap::LaunchConfiguration;
use std::path::PathBuf;
use std::collections::HashMap;
let mut env = HashMap::new();
env.insert("PERL5LIB".to_string(), "lib:local/lib/perl5".to_string());
let config = LaunchConfiguration {
program: PathBuf::from("${workspaceFolder}/script.pl"),
args: vec!["--debug".to_string()],
cwd: Some(PathBuf::from("${workspaceFolder}")),
env,
perl_path: Some(PathBuf::from("/usr/bin/perl")),
include_paths: vec![
PathBuf::from("lib"),
PathBuf::from("local/lib/perl5"),
],
};§Testing
The adapter includes comprehensive test coverage:
# Run all DAP tests
cargo test -p perl-dap
# Test specific phase
cargo test -p perl-dap bridge_adapter
# Integration tests
cargo test -p perl-dap --test integration_testsAll tests are tagged with acceptance criteria (AC1-AC19) for traceability:
#[test]
fn test_launch_config_validation() {
// AC:2 - Launch configuration validation
let config = LaunchConfiguration { /* ... */ };
assert!(config.validate().is_ok());
}§Security Considerations
- Command Injection: All paths and arguments are sanitized
- Arbitrary Execution: Evaluation restricted to debug context
- Resource Limits: Memory and time budgets for operations
- Path Validation: Prevent directory traversal and unauthorized access
§Error Handling
The adapter uses anyhow::Result for comprehensive error reporting:
use perl_dap::{BridgeAdapter, DapError};
async fn run_adapter() -> anyhow::Result<()> {
let mut adapter = BridgeAdapter::new();
adapter.spawn_pls_dap().await?;
adapter.proxy_messages().await?;
Ok(())
}§Integration with perl-parser
The DAP adapter leverages perl_parser for:
- Breakpoint Validation: Verify breakpoints on executable lines
- Variable Inspection: Type-aware variable rendering
- Expression Evaluation: Parse and evaluate debug expressions
- Source Mapping: Map positions between editor and runtime
§Migration Path
Phase 1 provides immediate value via bridging, while Phase 2 and 3 will gradually migrate functionality to native Rust implementation for better performance and integration.
Users can start with bridge mode today and transparently upgrade to native mode when Phase 2 is complete.
§Related Crates
perl_parser: Parsing engine and AST analysisperl_lsp: Language Server Protocol implementationperl_lexer: Context-aware Perl tokenizer
§Documentation
- DAP Specification: Debug Adapter Protocol
- Implementation Guide: See
docs/DAP_IMPLEMENTATION_GUIDE.md - Issue Tracking: See GitHub issue #207 for acceptance criteria
§Test-Driven Development
This crate follows TDD principles with acceptance criteria from Issue #207.
All tests are tagged with // AC:ID comments for traceability to specifications.
Re-exports§
pub use debug_adapter::var_ref::ScopeKind;pub use debug_adapter::var_ref::VariableReference;pub use debug_adapter::var_ref::VariableReferenceError;pub use bridge_adapter::BridgeAdapter;pub use bridge_adapter::DapBridgeEnvConfig;pub use configuration::AttachConfiguration;pub use configuration::LaunchConfiguration;pub use configuration::create_attach_json_snippet;pub use configuration::create_launch_json_snippet;pub use debug_adapter::DapMessage;pub use debug_adapter::DebugAdapter;pub use server::DapConfig;pub use server::DapMode;pub use server::DapServer;pub use breakpoints::BreakpointRecord;pub use breakpoints::BreakpointStore;pub use breakpoints::interpolate_logpoint_message;pub use protocol::AttachRequestArguments;pub use protocol::Breakpoint;pub use protocol::BreakpointLocation;pub use protocol::BreakpointLocationsArguments;pub use protocol::BreakpointLocationsResponseBody;pub use protocol::CancelArguments;pub use protocol::Capabilities;pub use protocol::CompletionItem;pub use protocol::CompletionsArguments;pub use protocol::CompletionsResponseBody;pub use protocol::ContinueArguments;pub use protocol::ContinueResponseBody;pub use protocol::DataBreakpoint;pub use protocol::DataBreakpointInfoArguments;pub use protocol::DataBreakpointInfoResponseBody;pub use protocol::DisconnectArguments;pub use protocol::EvaluateArguments;pub use protocol::EvaluateResponseBody;pub use protocol::Event;pub use protocol::ExceptionBreakpointFilter;pub use protocol::ExceptionDetails;pub use protocol::ExceptionFilterOption;pub use protocol::ExceptionInfoArguments;pub use protocol::ExceptionInfoResponseBody;pub use protocol::FunctionBreakpoint;pub use protocol::GotoArguments;pub use protocol::GotoTarget;pub use protocol::GotoTargetsArguments;pub use protocol::GotoTargetsResponseBody;pub use protocol::InitializeRequestArguments;pub use protocol::LaunchRequestArguments;pub use protocol::LoadedSourcesResponseBody;pub use protocol::Module;pub use protocol::ModulesArguments;pub use protocol::ModulesResponseBody;pub use protocol::NextArguments;pub use protocol::PauseArguments;pub use protocol::ProtocolStackFrame;pub use protocol::ProtocolVariable;pub use protocol::Request;pub use protocol::Response;pub use protocol::RestartArguments;pub use protocol::RestartFrameArguments;pub use protocol::Scope;pub use protocol::ScopesArguments;pub use protocol::ScopesResponseBody;pub use protocol::SetBreakpointsArguments;pub use protocol::SetBreakpointsResponseBody;pub use protocol::SetDataBreakpointsArguments;pub use protocol::SetDataBreakpointsResponseBody;pub use protocol::SetExceptionBreakpointsArguments;pub use protocol::SetExpressionArguments;pub use protocol::SetExpressionResponseBody;pub use protocol::SetFunctionBreakpointsArguments;pub use protocol::SetVariableArguments;pub use protocol::SetVariableResponseBody;pub use protocol::Source;pub use protocol::SourceArguments;pub use protocol::SourceBreakpoint;pub use protocol::SourceResponseBody;pub use protocol::StackTraceArguments;pub use protocol::StackTraceResponseBody;pub use protocol::StepInArguments;pub use protocol::StepInTarget;pub use protocol::StepInTargetsArguments;pub use protocol::StepInTargetsResponseBody;pub use protocol::StepOutArguments;pub use protocol::TerminateArguments;pub use protocol::TerminateThreadsArguments;pub use protocol::Thread;pub use protocol::ThreadsResponseBody;pub use protocol::VariablesArguments;pub use protocol::VariablesResponseBody;
Modules§
- api
- Explicit public API re-exports from all collapsed satellite modules. Explicit public API re-exports for Wave H collapsed modules.
- breakpoint
- AST-based breakpoint validation (from perl-dap-breakpoint). Breakpoint Validation for Perl DAP
- breakpoints
- Breakpoint storage and management for the DAP adapter. Breakpoint Management
- bridge_
adapter - Bridge adapter for communicating with Perl::LanguageServer’s DAP implementation. Bridge adapter for Perl::LanguageServer DAP
- command_
args - Platform-aware shell argument formatting (from perl-dap-command-args).
Platform-aware shell argument formatting used by
perl-dap. - config
- DAP launch and attach configuration types (from perl-dap-config). Standalone DAP launch and attach configuration structures
- configuration
- Launch and attach configuration structures for DAP debugging sessions. Backward-compatible re-export of the DAP configuration module.
- debug_
adapter - Debug Adapter Protocol (DAP) implementation for Perl debugging. Debug Adapter Protocol (DAP) implementation for Perl debugging
- eval
- Safe expression evaluation validation (from perl-dap-eval). Safe Expression Evaluation Validation for Perl DAP
- feature_
catalog - DAP feature catalog and capability gating helpers. DAP feature catalog and capability gating helpers.
- inline_
values - Inline value extraction for DAP
inlineValuesrequests. Inline value extraction for DAP inlineValues requests. - platform
- Cross-platform utilities for Perl path resolution and environment setup (from perl-dap-platform). Cross-platform utilities for Perl path resolution and environment setup.
- protocol
- DAP protocol types following the JSON-RPC 2.0 message format. DAP Protocol Types
- security
- Security validation and hardening (from perl-dap-security). Security validation module for DAP Phase 3 (AC16)
- server
- DAP server lifecycle, configuration, and operating mode.
- shell
- Shell-specific helpers for Perl DAP process launch (from perl-dap-shell). Shell-specific helpers for Perl DAP process launch.
- stack
- Stack trace parsing and frame classification (from perl-dap-stack). Stack trace handling for Perl DAP
- tcp_
attach - TCP-based attachment to running Perl debugger processes. TCP Attach Module for DAP
- types
- Shared DAP session model types (from perl-dap-types). Shared DAP session model types for Perl debugging.
- value
- Shared Perl value model for DAP parser and renderer (from perl-dap-value). Shared Perl value model for DAP parser and renderer crates.
- var_ref
- Type-safe variablesReference codec — retiring the #1219 ID/ref-space collision class.
- variables
- Variable parsing and rendering for Perl DAP (from perl-dap-variables). Variable rendering for Perl DAP