cargo-lsp 0.0.1

LSP for Cargo.toml files
use std::ops::{Deref, DerefMut};

use mylsp::prelude::*;
use toml::Table;

#[derive(Clone, Debug)]
pub struct Doc {
    uri: String,
    text: String,
    diagnostics: Diagnostics,
}

impl Doc {
    pub fn new(uri: &str, text: String) -> Self {
        let diagnostics = build_diagnostics(&text);
        Self {
            uri: uri.to_string(),
            text,
            diagnostics,
        }
    }

    pub fn diagnostics(&self) -> &Diagnostics {
        &self.diagnostics
    }
}

fn build_diagnostics(text: &str) -> Diagnostics {
    if let Err(err) = text.parse::<Table>() {
        return vec![toml_error_to_diagnostic(text, &err)].into();
    }
    let items = vec![];
    items.into()
}

fn toml_error_to_diagnostic(text: &str, err: &toml::de::Error) -> Diagnostic {
    let range = Range::from_text_position_range(text, err.span().unwrap_or(0..0));
    Diagnostic {
        range,
        severity: Some(DiagnosticSeverity::Error),
        code: None,
        code_description: None,
        source: None,
        message: err.message().to_string(),
        tags: None,
        related_information: None,
        data: None,
    }
}

#[derive(Default, Clone, Debug)]
pub struct Diagnostics(Vec<Diagnostic>);

impl From<Vec<Diagnostic>> for Diagnostics {
    fn from(value: Vec<Diagnostic>) -> Self {
        Self(value)
    }
}

impl Deref for Diagnostics {
    type Target = Vec<Diagnostic>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl DerefMut for Diagnostics {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

impl From<&Doc> for Notification {
    fn from(value: &Doc) -> Self {
        (
            "textDocument/publishDiagnostics",
            PublishDiagnosticsParams {
                uri: value.uri.clone(),
                version: None,
                diagnostics: value.diagnostics().to_vec(),
            },
        )
            .into()
    }
}

impl From<&Doc> for DocumentDiagnosticReport {
    fn from(value: &Doc) -> Self {
        DocumentDiagnosticReport {
            kind: "full".to_string(),
            result_id: None,
            items: value.diagnostics().to_vec(),
        }
    }
}