Skip to content

EffortlessMetrics/perl-lsp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4,153 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

perl-lsp logo

perl-lsp

CI crates.io Downloads docs.rs GitHub release License: MIT OR Apache-2.0 MSRV VSCode Marketplace Installs (manual) Open VSX Downloads


Perl has lacked a proper modern LSP implementation. Other languages — Rust, TypeScript, Go, Python — have mature language servers with fast completions, reliable navigation, and full debugger integration. Perl's existing options were slow, incomplete, or required a working Perl runtime just to get basic editor features. perl-lsp fills that gap: a native Rust implementation of the Language Server Protocol and Debug Adapter Protocol for Perl 5, with its own parser and lexer, no Perl runtime required for IDE features.

What It Is

perl-lsp is a workspace of Rust crates delivering a complete Perl 5 tooling stack: an LSP server (perllsp) implementing all 119 capabilities catalogued in features.toml (88 LSP + 24 DAP + 7 extension features), a DAP debug adapter, a recursive-descent parser, a context-aware lexer, and a semantic analyzer — packaged as a single native binary you can drop into any editor. It runs on Windows, macOS, and Linux.

Quick Start

VS Code — install the extension and you are done:

code --install-extension effortlessmetrics.perl-lsp-rs

The extension auto-downloads the matching perllsp binary for your platform.

Other editors — download a prebuilt binary from GitHub Releases, add it to your PATH, then point your LSP client at it:

-- Neovim (nvim-lspconfig)
require('lspconfig').perl_ls.setup { cmd = { "perllsp", "--stdio" } }
;; Emacs (eglot)
(add-to-list 'eglot-server-programs
             '((perl-mode cperl-mode) . ("perllsp" "--stdio")))
# Any generic LSP client
perllsp --stdio

Verify the install:

perllsp --health

For a full walkthrough, see docs/tutorials/GETTING_STARTED.md.

Note: Do not use cargo install perl-lsp — that name is owned by an unrelated project on crates.io. Use cargo install --path crates/perllsp to build from source.

Key Features

  • Full LSP surface — completions, diagnostics, hover, go-to-definition, find references, rename, formatting, semantic tokens, inlay hints, code actions, code lens, workspace symbols; every capability in features.toml has an implementation wired up (see what the numbers mean)
  • Native debug adapter — DAP breakpoints, stepping, stack frames, variable inspection, and evaluate; no wrapper script required
  • Fast native parser — recursive-descent v3 parser with a context-aware lexer; validated against a curated CPAN corpus
  • Semantic analysis — symbol resolution, scope tracking, Moose/Moo method modifiers and role composition
  • Refactoring — extract variable, extract subroutine, workspace-scoped rename, subroutine inlining
  • Diagnostics — dead code highlighting, strict/warnings diagnostics, perlcritic integration with walk-up discovery and explicit tooling warnings
  • Zero-Perl dependency for IDE features — the server is a single native binary
  • Windows first-class — install, path handling, and shell interactions are part of the release surface

Architecture

The native Rust parser stack is the architectural center of the workspace — the LSP server, diagnostics, hover, completion, and every other IDE feature read from it directly. Tree-sitter integration is an interop surface layered over that core, not a dependency of it.

Entry points for external consumers

Different users walk in through different doors. Pick the one that matches your use case:

You want to… Use
Get Perl IDE features in an editor VS Code extension (perl-lsp-rs) or the perllsp binary from Releases
Perl syntax support for tree-sitter consumers (Neovim, Helix, GitHub) tree-sitter-perl-c — conventional C grammar binding
Query a Perl AST from Rust with tree-sitter-style ergonomics tree-sitter-perl-rs — Rust-native facade over the v3 parser (in development)
Parse Perl from Rust directly with full fidelity perl-parser (+ perl-lexer) — the recursive-descent v3 parser
Tokenize Perl only perl-lexer — context-aware tokenizer, no parse tree
Resolve symbols and track scopes over a parsed Perl AST (including Moose/Moo method modifiers) perl-semantic-analyzer — scope tracking, symbol extraction, role composition
Index and search Perl symbols across a whole project perl-workspace-index — cross-file symbol index and refactoring orchestration
Validate Perl regex patterns for ReDoS, catastrophic backtracking, or embedded code execution perl-regex — safety/complexity checks (not a regex parser)
Generate Perl fixtures or test against a curated corpus perl-corpus — library plus perl-corpus CLI for proptest strategies, edge cases, and deterministic codegen
Debug Perl from a DAP-speaking editor perl-dap via the perllsp binary's DAP server mode

Workspace layers

Layer Crates Role
LSP server binary crates/perllsp, crates/perl-lsp Protocol loop, request dispatch
Debug adapter crates/perl-dap DAP server for stepping, breakpoints, evaluate
Parser stack (center) crates/perl-parser, crates/perl-lexer, crates/perl-parser-core Recursive-descent v3 parser and context-aware lexer — all IDE features read from this
Semantic analysis crates/perl-semantic-analyzer Scope tracking, symbol resolution, Moose/Moo handling
Workspace indexing crates/perl-workspace-index Cross-file symbol index
LSP feature providers crates/perl-lsp-* Per-feature crates (hover, definition, rename, …)
Tree-sitter interop crates/tree-sitter-perl-c, crates/tree-sitter-perl-rs See split below

Tree-sitter split. Two crates share the family name but play different roles:

  • tree-sitter-perl-c — the conventional C grammar binding, maintained for compatibility with tree-sitter consumers and as a reference point for comparison. Not on the LSP's critical path.
  • tree-sitter-perl-rs — a Rust-native facade over the v3 parser that exposes tree-sitter-compatible ergonomics without the C grammar. In development.

See docs/README.md for the full crate map and design notes.

Documentation

What you need Where to go
First-time setup docs/tutorials/GETTING_STARTED.md
Editor-specific config docs/how-to/EDITOR_SETUP.md
All configuration options docs/reference/CONFIG.md
Commands reference docs/reference/COMMANDS_REFERENCE.md
Upgrade guide docs/how-to/UPGRADING.md
Troubleshooting docs/how-to/TROUBLESHOOTING.md
Current status and metrics docs/project/status/index.md
Release roadmap docs/project/ROADMAP.md
Release history RELEASE_HISTORY.md
Full docs index docs/INDEX.md

Contributing

New contributor? Start with docs/contributing/FIRST_PR.md — clone to PR in five minutes.

cargo test --workspace --lib
cargo xtask fmt
cargo clippy --workspace
nix develop -c just ci-gate   # required before merge

Find beginner-friendly issues:

gh issue list --label "good-first-issue" --state open

See CONTRIBUTING.md for the full contributor workflow.

Status

Current release: v0.12.4 — public alpha. The 0.12.x line is building parser corpus confidence, diagnostic hardening, and distribution coverage toward the v0.13.0 public alpha announcement. See docs/project/ROADMAP.md for the milestone ladder and docs/project/status/index.md for live metrics.

What the numbers mean (and don't)

The project tracks a few distinct metrics that are easy to conflate. Each one scopes a different question:

Metric Current What it measures What it does not measure
LSP/DAP capability coverage 119 / 119 Every capability catalogued in features.toml has an implementation wired up Per-capability correctness, completeness on edge cases, or subjective UX quality
Parser corpus — CPAN top 1000 95.3% (8931 / 9372) File-level clean parse rate: share of files the parser processes without recording errors Semantic fidelity of the AST, cross-file analysis, or any LSP-level correctness
Parser corpus — Ubuntu system Perl 97.1% (6890 / 7095) Same, against the Ubuntu system-installed Perl compatibility baseline Same
Parser corpus — project corpus 100.0% (91 / 91) Deterministic regression baseline that must stay clean Same
End-to-end UX confidence qualitative Currently covered by manual editor smoke workflows, the perl-lsp-ux-tests first-5-minutes harness, and open-issue burn-down — not a published number Anything about parser breadth, protocol catalog size, or capability count

The last row is the important one: none of the automated metrics above measure whether a real editing session feels good. That's validated through workflow smoke tests, the perl-lsp-ux-tests harness, and the list of known gaps below, not by a dashboard.

Live numbers live in docs/project/status/parser.md; this table may lag a merge cycle.

Known gaps toward solid UX

The table below is the honest state of v0.13.0 rough edges. None block basic use; all affect realistic workflows.

Must land for v0.13.0

  • Workspace-wide rename slice — multi-root workspace support shipped in 0.12.x (PR #3984: per-folder config loading, WorkspaceFolderState, cross-folder integration); workspace-wide rename and module-move are roughly 30% complete, conditionally in scope pending verification (#3522)

Nice to land

  • Dynamic require / literal importrequire Module; Module->import('sym') with static string names: goto-def on the bareword should resolve to the definition site; @ISA / use parent / use base chains and use Module qw(...) list imports already work; this is the remaining slice of the import visibility lane (#3476, tracked by umbrella #4246)

Deferred to v0.14.0

  • Dynamic workspace configuration — per-folder .perl-lsp.toml is the supported v0.13 mechanism; fully dynamic per-folder scoping via the workspace/configuration reverse-request flow is deferred (#3515)

What shipped this cycle (v0.12.x)

These items were rough edges in the previous list and have since landed:

  • Parser error recovery: unclosed block recovery (PR #4079), symbol extractor descends into partial Error nodes (PR #4071) — #3499 closed
  • Import list bareword resolution for use Module qw(...) and tag imports — #3472 closed
  • use constant symbols tracked in visible symbol table — #3475 closed
  • Pragma tracker: use if, feature bundles, eval/sub-scoped pragma leakage (PRs #4050, #4038, #4052), conservative eval STRING handling (PR #4052) — #3489 closed

Security

Release artifacts include SBOM generation and provenance attestations. See docs/reference/SUPPLY_CHAIN_SECURITY.md.

License

Dual licensed under MIT or Apache-2.0: LICENSE-MIT / LICENSE-APACHE