lsp 0.1.1

Language Server Protocol
Documentation
//! # Language Server Protocol (LSP)
//!
//! This crate provides types for the [Language Server Protocol](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/).
//! It makes no assumptions about the transport layer (e.g. TCP, Unix sockets,
//! etc.), or if the consumer is a client or server.
//!
//! This crate uses [`serde`] for all encodable types, and a custom [`Uri`] type
//! for URIs.
//!
//! # Features
//!
//! - `raw_value` - Use [`serde_json::value::RawValue`] for `LSPAny` instead of
//!   [`serde_json::Value`].
//!
//! # Version
//!
//! Almost all types in this crate are generated from the [LSP
//! model](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/metaModel/metaModel.json).
//! This code was generated from LSP version
#![doc = concat!("**", include_str!("lsp_version.txt"), "**.")]
//!

#![allow(rustdoc::redundant_explicit_links)] // explicit links are simpler
#![allow(deprecated)] // we need to use the deprecated types

pub mod notification;
pub mod request;

mod types;
pub use types::*;

mod uri;
pub use uri::Uri;

#[cfg(not(feature = "raw_value"))]
type Value = serde_json::Value;
#[cfg(feature = "raw_value")]
type Value = Box<serde_json::value::RawValue>;

use serde::{Deserialize, Serialize};

/// Represents a union of two types. The first variant will take priority when
/// deserializing (using `#[serde(untagged)]` behavior). Additionally, the first
/// variant is the default.
///
/// This relies on the LSP spec putting the "default" variant first. Ordering is
/// maintained between unions in the LSP spec and the order of generic arguments
/// in generated code.
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(not(feature = "raw_value"), derive(Deserialize))]
#[serde(untagged)]
pub enum Or2<A, B> {
  A(A),
  B(B),
}

/// Represents a union of three types. The first variant will take priority when
/// deserializing (using `#[serde(untagged)]` behavior). Additionally, the first
/// variant is the default.
///
/// This relies on the LSP spec putting the "default" variant first. Ordering is
/// maintained between unions in the LSP spec and the order of generic arguments
/// in generated code.
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(not(feature = "raw_value"), derive(Deserialize))]
#[serde(untagged)]
pub enum Or3<A, B, C> {
  A(A),
  B(B),
  C(C),
}

// `#[serde(untagged)]` buffers content into serde's internal `Content` type
// before trying each variant. serde_json's `RawValue` requires serde_json's own
// deserializer and breaks when fed a `ContentDeserializer`. Using
// `Box<RawValue>` as the intermediate captures raw JSON bytes, and
// `serde_json::from_str` gives each variant attempt a proper serde_json
// deserializer.
#[cfg(feature = "raw_value")]
impl<'de, A: serde::de::DeserializeOwned, B: serde::de::DeserializeOwned> Deserialize<'de>
  for Or2<A, B>
{
  fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
    let raw = Box::<serde_json::value::RawValue>::deserialize(d)?;

    let res_a = serde_json::from_str::<A>(raw.get());
    let err_a = match res_a {
      Ok(a) => return Ok(Or2::A(a)),
      Err(e) => e,
    };

    let res_b = serde_json::from_str::<B>(raw.get());
    let err_b = match res_b {
      Ok(b) => return Ok(Or2::B(b)),
      Err(e) => e,
    };

    Err(serde::de::Error::custom(format!(
      "Failed to deserialize as both {}: {} and {}: {}",
      std::any::type_name::<A>(),
      err_a,
      std::any::type_name::<B>(),
      err_b,
    )))
  }
}

#[cfg(feature = "raw_value")]
impl<
  'de,
  A: serde::de::DeserializeOwned,
  B: serde::de::DeserializeOwned,
  C: serde::de::DeserializeOwned,
> Deserialize<'de> for Or3<A, B, C>
{
  fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
    let raw = Box::<serde_json::value::RawValue>::deserialize(d)?;

    let res_a = serde_json::from_str::<A>(raw.get());
    let err_a = match res_a {
      Ok(a) => return Ok(Or3::A(a)),
      Err(e) => e,
    };

    let res_b = serde_json::from_str::<B>(raw.get());
    let err_b = match res_b {
      Ok(b) => return Ok(Or3::B(b)),
      Err(e) => e,
    };

    let res_c = serde_json::from_str::<C>(raw.get());
    let err_c = match res_c {
      Ok(c) => return Ok(Or3::C(c)),
      Err(e) => e,
    };

    Err(serde::de::Error::custom(format!(
      "Failed to deserialize as any of {}: {}, {}: {}, and {}: {}",
      std::any::type_name::<A>(),
      err_a,
      std::any::type_name::<B>(),
      err_b,
      std::any::type_name::<C>(),
      err_c,
    )))
  }
}

impl<A: Default, B> Default for Or2<A, B> {
  fn default() -> Self { Or2::A(A::default()) }
}

impl<A: Default, B, C> Default for Or3<A, B, C> {
  fn default() -> Self { Or3::A(A::default()) }
}

#[derive(serde::Deserialize)]
#[serde(tag = "kind")]
#[serde(rename_all = "camelCase")]
pub enum WorkDoneProgress {
  Begin(WorkDoneProgressBegin),
  Report(WorkDoneProgressReport),
  End(WorkDoneProgressEnd),
}

#[cfg(test)]
mod tests {
  use serde::de::DeserializeOwned;

  use super::*;

  macro_rules! assert_serde {
    ($value:expr, $expected:literal as $ty:ty) => {
      assert_eq!(ser($value), $expected);
      // This is dumb but it works.
      assert_eq!(format!("{:?}", de::<$ty>($expected)), format!("{:?}", $value));
    };
  }

  fn ser<T: Serialize>(t: &T) -> String { serde_json::to_string(t).unwrap() }
  fn de<T: DeserializeOwned>(t: &str) -> T { serde_json::from_str(t).unwrap() }

  #[test]
  fn string_enums_work() {
    assert_serde!(
      &[
        PositionEncodingKind::Utf8,
        PositionEncodingKind::Utf16,
        PositionEncodingKind::Custom("foo".into())
      ],
      r#"["utf-8","utf-16","foo"]"# as Vec<PositionEncodingKind>
    );
  }

  #[test]
  fn empty_caps_works() {
    assert_serde!(&ClientCapabilities::default(), r#"{}"# as ClientCapabilities);
    assert_serde!(&ServerCapabilities::default(), r#"{}"# as ServerCapabilities);
  }

  #[test]
  fn or2_works() {
    assert_serde!(
      &TextDocumentSyncOptions { save: Some(Or2::A(true)), ..Default::default() },
      r#"{"save":true}"# as TextDocumentSyncOptions
    );

    assert_serde!(
      &TextDocumentSyncOptions { save: Some(Or2::B(SaveOptions::default())), ..Default::default() },
      r#"{"save":{}}"# as TextDocumentSyncOptions
    );

    assert_serde!(
      &TextDocumentSyncOptions {
        save: Some(Or2::B(SaveOptions { include_text: Some(true), ..Default::default() })),
        ..Default::default()
      },
      r#"{"save":{"includeText":true}}"# as TextDocumentSyncOptions
    );
  }

  // Tests untagged values + raw values. These fundamentally do not work together:
  // serde's default untagged deserializer breaks serde_json's raw value
  // deserializer. So, we have a custom untagged deserializer, which just uses
  // raw_value directly. This is to test that all these bit's play
  // nicely together.
  #[test]
  fn double_untagged() {
    type DoubleUntagged = Or2<u32, DoubleObj>;
    #[derive(Debug, Serialize, Deserialize)]
    struct DoubleObj {
      outer: Or2<u32, SingleObj>,
    }
    #[derive(Debug, Serialize, Deserialize)]
    struct SingleObj {
      inner: Value,
    }

    assert_serde!(
      &DoubleUntagged::B(DoubleObj {
        outer: Or2::B(SingleObj {
          #[cfg(not(feature = "raw_value"))]
          inner:                                    Value::Number(3.into()),
          #[cfg(feature = "raw_value")]
          inner:                                    serde_json::value::RawValue::from_string(
            "3".into()
          )
          .unwrap(),
        }),
      }),
      r#"{"outer":{"inner":3}}"# as DoubleUntagged
    );
  }
}