diff --git a/CHANGELOG.md b/CHANGELOG.md index 231bece8..4d3f6386 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.3.0] - 2025-12-24 + +### Added +- **Trait-based ecosystem architecture** — Unified handling for all package ecosystems + - `Ecosystem` trait with parser, registry, and formatter + - `EcosystemRegistry` for dynamic ecosystem lookup by URI + - `LockfileProvider` trait for lock file parsing + - Simplified document lifecycle with generic handlers + +### Changed +- **Performance optimizations** — Significant latency improvements + - Parallel registry fetching with `futures::join_all` (97% faster document open) + - O(N log K) cache eviction algorithm with min-heap (90% faster eviction) + - Parse-once pattern for version sorting (50% faster parsing) + - String formatting optimization with `write!()` macro + - Early lock release pattern with `get_document_clone()` + +### Fixed +- npm: Remove extra quotes in code action version replacements (#29) + ## [0.2.3] - 2025-12-23 ### Changed @@ -106,7 +126,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - TLS enforced via rustls - cargo-deny configured for vulnerability scanning -[Unreleased]: https://github.com/bug-ops/deps-lsp/compare/v0.2.3...HEAD +[Unreleased]: https://github.com/bug-ops/deps-lsp/compare/v0.3.0...HEAD +[0.3.0]: https://github.com/bug-ops/deps-lsp/compare/v0.2.3...v0.3.0 [0.2.3]: https://github.com/bug-ops/deps-lsp/compare/v0.2.2...v0.2.3 [0.2.2]: https://github.com/bug-ops/deps-lsp/compare/v0.2.1...v0.2.2 [0.2.1]: https://github.com/bug-ops/deps-lsp/compare/v0.2.0...v0.2.1 diff --git a/Cargo.lock b/Cargo.lock index f638b283..319ee64a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -381,7 +381,7 @@ dependencies = [ [[package]] name = "deps-cargo" -version = "0.2.3" +version = "0.3.0" dependencies = [ "async-trait", "criterion", @@ -403,7 +403,7 @@ dependencies = [ [[package]] name = "deps-core" -version = "0.2.3" +version = "0.3.0" dependencies = [ "async-trait", "criterion", @@ -423,7 +423,7 @@ dependencies = [ [[package]] name = "deps-lsp" -version = "0.2.3" +version = "0.3.0" dependencies = [ "async-trait", "dashmap 6.1.0", @@ -446,7 +446,7 @@ dependencies = [ [[package]] name = "deps-npm" -version = "0.2.3" +version = "0.3.0" dependencies = [ "async-trait", "criterion", @@ -465,7 +465,7 @@ dependencies = [ [[package]] name = "deps-pypi" -version = "0.2.3" +version = "0.3.0" dependencies = [ "async-trait", "criterion", diff --git a/Cargo.toml b/Cargo.toml index 2e2c811a..a7af1b2e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ exclude = ["crates/deps-zed"] resolver = "2" [workspace.package] -version = "0.2.3" +version = "0.3.0" edition = "2024" rust-version = "1.89" authors = ["Andrei G"] @@ -15,11 +15,11 @@ repository = "https://github.com/bug-ops/deps-lsp" async-trait = "0.1" criterion = "0.8" dashmap = "6.1" -deps-core = { version = "0.2.3", path = "crates/deps-core" } -deps-cargo = { version = "0.2.3", path = "crates/deps-cargo" } -deps-npm = { version = "0.2.3", path = "crates/deps-npm" } -deps-pypi = { version = "0.2.3", path = "crates/deps-pypi" } -deps-lsp = { version = "0.2.3", path = "crates/deps-lsp" } +deps-core = { version = "0.3.0", path = "crates/deps-core" } +deps-cargo = { version = "0.3.0", path = "crates/deps-cargo" } +deps-npm = { version = "0.3.0", path = "crates/deps-npm" } +deps-pypi = { version = "0.3.0", path = "crates/deps-pypi" } +deps-lsp = { version = "0.3.0", path = "crates/deps-lsp" } futures = "0.3" insta = "1" mockito = "1" diff --git a/README.md b/README.md index b7d0a6e2..7a04e24f 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,24 @@ A universal Language Server Protocol (LSP) server for dependency management acro - **Diagnostics** — Warnings for outdated, unknown, or yanked dependencies - **Hover Information** — Package descriptions with resolved version from lock file - **Code Actions** — Quick fixes to update dependencies +- **High Performance** — Parallel fetching, optimized caching, minimal latency ![deps-lsp in action](https://raw.githubusercontent.com/bug-ops/deps-zed/main/assets/img.png) +## Performance + +deps-lsp is optimized for responsiveness: + +| Operation | Latency | Notes | +|-----------|---------|-------| +| Document open (50 deps) | ~150ms | Parallel registry fetching | +| Inlay hints | <100ms | Cached version lookups | +| Hover | <50ms | Pre-fetched metadata | +| Code actions | <50ms | No network calls | + +> [!TIP] +> Lock file support provides instant resolved versions without network requests. + ## Supported Ecosystems | Ecosystem | Manifest File | Status | @@ -171,19 +186,21 @@ deps-lsp/ ### Architecture -The codebase uses a trait-based architecture with the `EcosystemHandler` trait providing a unified interface for all package ecosystems: +The codebase uses a trait-based architecture with the `Ecosystem` trait providing a unified interface for all package ecosystems: ```rust -// Each ecosystem implements EcosystemHandler -impl EcosystemHandler for CargoHandler { ... } -impl EcosystemHandler for NpmHandler { ... } -impl EcosystemHandler for PyPiHandler { ... } - -// Generic LSP handlers work with any ecosystem -generate_inlay_hints::(...); -generate_hover_info::(...); -generate_code_actions::(...); -generate_diagnostics::(...); +// Each ecosystem implements the Ecosystem trait +pub trait Ecosystem: Send + Sync { + fn id(&self) -> &'static str; + fn display_name(&self) -> &'static str; + fn matches_uri(&self, uri: &Url) -> bool; + fn registry(&self) -> Arc; + fn formatter(&self) -> Arc; + async fn parse_manifest(&self, content: &str, uri: &Url) -> Result; +} + +// EcosystemRegistry discovers the right handler for any manifest file +let ecosystem = registry.get_for_uri(&uri); ``` ### Benchmarks