Skip to content

Commit

Permalink
feat: sync text documents
Browse files Browse the repository at this point in the history
  • Loading branch information
viddrobnic committed Jul 27, 2024
1 parent 236c918 commit fa563ab
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 6 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions language_server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ edition = "2021"
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
thiserror = "1.0"
7 changes: 7 additions & 0 deletions language_server/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use thiserror::Error;

#[derive(Debug, Error)]
pub enum Error {
#[error("invalid parameters: {0}")]
ExtractError(#[from] serde_json::Error),
}
63 changes: 58 additions & 5 deletions language_server/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
use core::fmt;
use std::{
collections::HashMap,
fs::{self, OpenOptions},
io::{self, Write},
path::PathBuf,
};

use error::Error;
use message::{initialize::*, *};
use text::{DidChangeTextDocumentParams, DidCloseTextDocumentParams, DidOpenTextDocumentParams};

pub mod error;
mod message;

#[derive(Clone, Copy)]
Expand All @@ -20,6 +24,7 @@ enum LogLevel {

pub struct Server {
log_file: Option<fs::File>,
documents: HashMap<String, String>,
}

impl fmt::Display for LogLevel {
Expand All @@ -45,7 +50,10 @@ impl Server {
.expect("Failed to open log file")
});

Self { log_file }
Self {
log_file,
documents: HashMap::new(),
}
}

fn log(&mut self, level: LogLevel, message: &str) {
Expand Down Expand Up @@ -75,19 +83,64 @@ impl Server {
msg.write(&mut stdout).unwrap();
self.log(LogLevel::Debug, "Writtten response")
}
Message::Notification(notification) => self.handle_notification(notification),
Message::Notification(notification) => {
let res = self.handle_notification(notification);
if let Err(err) = res {
self.log(
LogLevel::Error,
&format!("Invalid notification params: {}", err),
);
}
}
Message::Response(_) => {
unreachable!("Got response from client instead of request/notification")
}
}
}
}

fn handle_notification(&mut self, notification: Notification) {
fn handle_notification(&mut self, notification: Notification) -> Result<(), Error> {
self.log(
LogLevel::Info,
&format!("Got notification: {:?}", notification),
LogLevel::Debug,
&format!("Got notification: {}", &notification.method),
);

match notification.method.as_ref() {
"textDocument/didOpen" => {
let params: DidOpenTextDocumentParams = notification.extract()?;
let params = params.text_document;
self.log(
LogLevel::Info,
&format!("Setting contents for opened file: {}", params.uri),
);

self.documents.insert(params.uri, params.text);
}
"textDocument/didChange" => {
let mut params: DidChangeTextDocumentParams = notification.extract()?;
self.log(
LogLevel::Info,
&format!("Updating contents for file: {}", params.text_document.uri),
);

if let Some(content) = params.content_changes.pop() {
self.documents
.insert(params.text_document.uri, content.text);
}
}
"textDocument/didClose" => {
let params: DidCloseTextDocumentParams = notification.extract()?;
self.log(
LogLevel::Info,
&format!("Closing file: {}", params.text_document.uri),
);

self.documents.remove(&params.text_document.uri);
}
_ => (),
}

Ok(())
}

fn handle_request(&mut self, req: Request) -> Response {
Expand Down
19 changes: 18 additions & 1 deletion language_server/src/message/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use std::{fmt, io};

use headers::Headers;
use serde::{Deserialize, Serialize};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde_json::Value;

use crate::error::Error;

mod headers;
pub mod initialize;
pub mod text;

#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
Expand Down Expand Up @@ -170,3 +173,17 @@ impl Response {
}
}
}

impl Request {
pub fn extract<P: DeserializeOwned>(self) -> Result<(RequestId, P), Error> {
let params = serde_json::from_value(self.params)?;
Ok((self.id, params))
}
}

impl Notification {
pub fn extract<P: DeserializeOwned>(self) -> Result<P, Error> {
let params = serde_json::from_value(self.params)?;
Ok(params)
}
}
36 changes: 36 additions & 0 deletions language_server/src/message/text.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DidOpenTextDocumentParams {
pub text_document: TextDocumentItem,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TextDocumentItem {
pub uri: String,
pub text: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DidChangeTextDocumentParams {
pub text_document: TextDocumentIdentifier,
pub content_changes: Vec<TextDocumentContentChangeEvent>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TextDocumentIdentifier {
pub uri: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TextDocumentContentChangeEvent {
pub text: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DidCloseTextDocumentParams {
pub text_document: TextDocumentIdentifier,
}

0 comments on commit fa563ab

Please sign in to comment.