Skip to main content

shipwright_zed/
lib.rs

1//! Zed-facing helpers for shipwright host integrations.
2//!
3//! Zed extensions often cannot run native `--version` probes before the
4//! language server starts. This crate re-exports the pure host resolver and
5//! adds small helpers for representing deferred LSP checks and validating the
6//! `serverInfo` payload returned from LSP `initialize`.
7
8#![forbid(unsafe_code)]
9
10pub use shipwright_host::{
11    resolve, DeferredCheck, DotnetToolConfig, EnvConfig, ErrorCode, ErrorDetails, PkgmgrConfig,
12    Platform, ProbedVersion, PromptAction, Resolution, ResolveInput, Source, Status, WarningCode,
13};
14
15/// The `serverInfo` subset Zed can verify from an LSP initialize response.
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub struct LspServerInfo<'a> {
18    /// Server name returned by `InitializeResult.serverInfo.name`.
19    pub name: &'a str,
20    /// Server version returned by `InitializeResult.serverInfo.version`.
21    pub version: &'a str,
22}
23
24/// Build a deferred LSP version-check result for a resolved command path.
25#[must_use]
26pub fn deferred_lsp_resolution(source: Source, command_path: impl Into<String>) -> Resolution {
27    Resolution::deferred(source, command_path.into(), DeferredCheck::LspInitialize)
28}
29
30/// Verify LSP `serverInfo` against the manifest component id and version.
31#[must_use]
32pub fn verify_lsp_server_info(
33    component_id: &str,
34    expected_version: &str,
35    server_info: Option<LspServerInfo<'_>>,
36) -> Resolution {
37    match server_info {
38        Some(info) if info.name != component_id => {
39            Resolution::error(ErrorCode::BinaryNameMismatch, None)
40        }
41        Some(info) if info.version == expected_version => Resolution::ok(
42            Source::LspInitialize,
43            component_id.to_string(),
44            info.version.to_string(),
45        ),
46        Some(info) => Resolution::error(
47            ErrorCode::NoSourceResolved,
48            Some(ErrorDetails {
49                expected: expected_version.to_string(),
50                found: info.version.to_string(),
51                at: component_id.to_string(),
52            }),
53        ),
54        None => Resolution::error(
55            ErrorCode::NoSourceResolved,
56            Some(ErrorDetails {
57                expected: expected_version.to_string(),
58                found: String::new(),
59                at: component_id.to_string(),
60            }),
61        ),
62    }
63}