Skip to main content

Crate perl_dap

Crate perl_dap 

Source
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 to Perl::LanguageServer for 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 negotiation
  • attach / launch - Debug session start
  • configurationDone - Initialization complete
  • disconnect - Session termination

§Breakpoints

  • setBreakpoints - Set breakpoints with AST validation
  • setFunctionBreakpoints - Break on function entry
  • setExceptionBreakpoints - Break on exceptions

§Execution Control

  • continue - Resume execution
  • next - Step over
  • stepIn - Step into
  • stepOut - Step out
  • pause - Pause execution

§Inspection

  • threads - List active threads
  • stackTrace - Get call stack
  • scopes - Get variable scopes
  • variables - Inspect variables with lazy loading
  • evaluate - 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_tests

All 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.

  • perl_parser: Parsing engine and AST analysis
  • perl_lsp: Language Server Protocol implementation
  • perl_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 inlineValues requests. 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