diff --git a/Cargo.lock b/Cargo.lock index 01f65986..52730fd7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -297,6 +297,17 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "auto_impl" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "autocfg" version = "1.4.0" @@ -730,6 +741,33 @@ dependencies = [ "syn 2.0.79", ] +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown", + "lock_api", + "once_cell", + "parking_lot_core", +] + [[package]] name = "dbusmenu-glib" version = "0.1.0" @@ -852,6 +890,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "dyn-clone" version = "1.0.17" @@ -1081,6 +1130,15 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + [[package]] name = "fsevent-sys" version = "4.1.0" @@ -1569,6 +1627,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9958ab3ce3170c061a27679916bd9b969eceeb5e8b120438e6751d0987655c42" +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + [[package]] name = "humantime" version = "2.1.0" @@ -1598,12 +1662,151 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "ident_case" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + [[package]] name = "indexmap" version = "2.5.0" @@ -1883,6 +2086,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + [[package]] name = "lock_api" version = "0.4.12" @@ -1899,6 +2108,31 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "lsp" +version = "0.1.0" +dependencies = [ + "codespan-reporting", + "dashmap 6.1.0", + "eww_shared_util", + "tokio", + "tower-lsp", + "yuck", +] + +[[package]] +name = "lsp-types" +version = "0.94.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66bfd44a06ae10647fe3f8214762e9369fd4248df1350924b4ef9e770a85ea1" +dependencies = [ + "bitflags 1.3.2", + "serde", + "serde_json", + "serde_repr", + "url", +] + [[package]] name = "maplit" version = "1.0.2" @@ -2129,6 +2363,12 @@ dependencies = [ "regex", ] +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + [[package]] name = "petgraph" version = "0.6.5" @@ -2206,6 +2446,26 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" +[[package]] +name = "pin-project" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "pin-project-lite" version = "0.2.14" @@ -2746,6 +3006,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "static_assertions" version = "1.1.0" @@ -2815,6 +3081,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "sysinfo" version = "0.31.4" @@ -2914,6 +3191,16 @@ dependencies = [ "syn 2.0.79", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tokio" version = "1.40.0" @@ -3002,6 +3289,66 @@ dependencies = [ "winnow", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-lsp" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ba052b54a6627628d9b3c34c176e7eda8359b7da9acd497b9f20998d118508" +dependencies = [ + "async-trait", + "auto_impl", + "bytes", + "dashmap 5.5.3", + "futures", + "httparse", + "lsp-types", + "memchr", + "serde", + "serde_json", + "tokio", + "tokio-util", + "tower", + "tower-lsp-macros", + "tracing", +] + +[[package]] +name = "tower-lsp-macros" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84fd902d4e0b9a4b27f2f440108dc034e1758628a9b702f8ec61ad66355422fa" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + [[package]] name = "tracing" version = "0.1.40" @@ -3074,12 +3421,36 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + [[package]] name = "urlencoding" version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -3444,6 +3815,18 @@ dependencies = [ "memchr", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "x11" version = "2.21.0" @@ -3487,6 +3870,30 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", + "synstructure", +] + [[package]] name = "yuck" version = "0.1.0" @@ -3593,6 +4000,49 @@ dependencies = [ "syn 2.0.79", ] +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", + "synstructure", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "zvariant" version = "3.15.2" diff --git a/crates/lsp/Cargo.toml b/crates/lsp/Cargo.toml new file mode 100644 index 00000000..50468b9f --- /dev/null +++ b/crates/lsp/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "lsp" +version = "0.1.0" +edition = "2021" + +[dependencies] +dashmap = "6.1.0" +tokio.workspace = true +tower-lsp = "0.20.0" +yuck = { path = "../yuck"} +eww_shared_util = { path = "../eww_shared_util"} +codespan-reporting.workspace = true diff --git a/crates/lsp/src/documents.rs b/crates/lsp/src/documents.rs new file mode 100644 index 00000000..e1947920 --- /dev/null +++ b/crates/lsp/src/documents.rs @@ -0,0 +1,120 @@ +use dashmap::{ + mapref::{multiple::RefMulti, one::Ref}, + DashMap, +}; +use eww_shared_util::Span; +use tower_lsp::lsp_types::Url; +use yuck::{ + config::{ + file_provider::{FilesError, YuckFileProvider}, + Config, + }, + error::DiagError, + parser::ast::Ast, +}; + +#[derive(PartialEq, Clone)] +pub enum DocSource { + String, + File(Url), +} + +#[derive(Clone)] +pub struct Document { + name: String, + text: String, + source: DocSource, + line_starts: Vec, + source_len_bytes: usize, +} + +#[derive(Clone)] +pub struct LspDocuments(pub DashMap); + +impl LspDocuments { + pub fn new() -> Self { + Self(DashMap::new()) + } + + pub fn get_file(&self, url: &Url) -> Result, codespan_reporting::files::Error> { + self.0 + .iter() + .find(|v| match &v.source { + DocSource::File(f) => f == url, + _ => false, + }) + .ok_or(codespan_reporting::files::Error::FileMissing) + } + + pub fn get_file_from_idx(&self, index: usize) -> Result, codespan_reporting::files::Error> { + self.0.get(&index).ok_or(codespan_reporting::files::Error::FileMissing) + } + + pub fn insert_file(&self, doc: Document) -> usize { + let id = self.0.len(); + self.0.insert(id, doc).ok_or(codespan_reporting::files::Error::FileMissing); + id + } + + pub fn insert_string(&self, name: String, content: String) -> usize { + let line_starts: Vec<_> = codespan_reporting::files::line_starts(&content).collect(); + let id = self.0.len(); + self.0 + .insert(id, Document { name, source: DocSource::String, line_starts, source_len_bytes: content.len(), text: content }) + .ok_or(codespan_reporting::files::Error::FileMissing); + id + } + + pub fn insert_url(&self, url: Url, content: String) -> usize { + let line_starts: Vec<_> = codespan_reporting::files::line_starts(&content).collect(); + let doc = Document { + name: url.to_string(), + source: DocSource::File(url.clone()), + line_starts, + source_len_bytes: content.len(), + text: content, + }; + + if let Ok(res) = self.get_file(&url) { + let id = *res.key(); + self.0.insert(id, doc); + return id; + } + + let id = self.0.len(); + self.0.insert(id, doc).ok_or(codespan_reporting::files::Error::FileMissing); + id + } +} + +impl YuckFileProvider for LspDocuments { + fn load_yuck_file(&mut self, path: std::path::PathBuf) -> Result<(Span, Vec), FilesError> { + let file_content = std::fs::read_to_string(&path)?; + let line_starts = codespan_reporting::files::line_starts(&file_content).collect(); + + // TODO this is very bad and very stupid + let source = match Url::from_file_path(&path) { + Ok(v) => DocSource::File(v), + Err(_) => DocSource::String, + }; + + let document = Document { + name: path.display().to_string(), + text: file_content.clone(), + line_starts, + source_len_bytes: file_content.len(), + source, + }; + let file_id = self.insert_file(document); + Ok(yuck::parser::parse_toplevel(file_id, file_content)?) + } + + fn load_yuck_str(&mut self, name: String, content: String) -> Result<(Span, Vec), DiagError> { + let file_id = self.insert_string(name, content.clone()); + yuck::parser::parse_toplevel(file_id, content) + } + + fn unload(&mut self, id: usize) { + self.0.remove(&id); + } +} diff --git a/crates/lsp/src/lib.rs b/crates/lsp/src/lib.rs new file mode 100644 index 00000000..6e5c5b29 --- /dev/null +++ b/crates/lsp/src/lib.rs @@ -0,0 +1,95 @@ +use std::sync::{Arc, Mutex}; + +use dashmap::DashMap; +use documents::LspDocuments; +use tower_lsp::jsonrpc::Result; +use tower_lsp::{lsp_types::*, Client, LanguageServer}; +use yuck::config::Config; + +mod documents; + +use yuck::error::DiagError; +use yuck::parser::parse_toplevel; + +pub type ArcM = Arc>; + +pub struct Backend { + pub client: Client, + documents: LspDocuments, + config: ArcM>, + errors: ArcM>, +} + +#[tower_lsp::async_trait] +impl LanguageServer for Backend { + async fn initialize(&self, _: InitializeParams) -> Result { + Ok(InitializeResult { + capabilities: ServerCapabilities { document_highlight_provider: Some(OneOf::Left(true)), ..Default::default() }, + server_info: None, + }) + } + + async fn shutdown(&self) -> Result<()> { + Ok(()) + } + + async fn initialized(&self, _: InitializedParams) { + self.client.log_message(MessageType::INFO, "server initialized!").await; + } + + async fn did_open(&self, params: DidOpenTextDocumentParams) { + self.change_document(TextDocumentItem { + uri: params.text_document.uri, + version: Some(params.text_document.version), + text: params.text_document.text, + }) + .await; + } + + async fn did_change(&self, mut params: DidChangeTextDocumentParams) { + self.change_document(TextDocumentItem { + uri: params.text_document.uri, + version: Some(params.text_document.version), + text: params.content_changes.swap_remove(0).text, + }) + .await; + } +} + +pub struct TextDocumentItem { + uri: Url, + text: String, + version: Option, +} + +impl Backend { + pub fn new(client: Client) -> Self { + Self { client, documents: LspDocuments::new(), config: Default::default(), errors: Default::default() } + } + + async fn change_document(&self, doc: TextDocumentItem) { + let file_id = self.documents.insert_url(doc.uri, doc.text.clone()); + let mut new_errors = Vec::new(); + + let mut errors = self.errors.lock().unwrap(); + let mut config = self.config.lock().unwrap(); + + let mut new_documents = self.documents.clone(); + *config = match parse_toplevel(file_id, doc.text).map(|(_, asts)| Config::generate(&mut new_documents, asts)) { + Ok(Ok(v)) => Some(v), + Err(e) | Ok(Err(e)) => { + new_errors.push(e); + None + } + }; + *errors = new_errors; + + // TODO this is extremely stupid, but I need to do this so I don't mutate self. + // A solution that doesn't need to mutate `self.documents` would be ideal, but + // `Config::generate` needs to mutate the documents. Unsure how best to handle this + self.documents.0.clear(); + new_documents.0.into_iter().for_each(|v| { + self.documents.0.insert(v.0, v.1); + }); + } +} diff --git a/crates/lsp/src/main.rs b/crates/lsp/src/main.rs new file mode 100644 index 00000000..5fbb4794 --- /dev/null +++ b/crates/lsp/src/main.rs @@ -0,0 +1,12 @@ +use lsp::Backend; +use tower_lsp::{LspService, Server}; + +#[tokio::main] +async fn main() { + let stdin = tokio::io::stdin(); + let stdout = tokio::io::stdout(); + + let (service, socket) = LspService::build(|client| Backend::new(client)).finish(); + + Server::new(stdin, stdout, socket).serve(service).await; +}