1use std::{fs::File, io::Write, path::PathBuf, str::FromStr};23use lsp_server::{Connection, ErrorCode, Message, Request, RequestId, Response};4use lsp_types::{5 notification::{DidChangeTextDocument, DidOpenTextDocument, Notification},6 request::{DocumentLinkRequest, HoverRequest},7 CompletionOptions, DidChangeTextDocumentParams, DidOpenTextDocumentParams, DocumentLink,8 DocumentLinkOptions, ServerCapabilities, TextDocumentSyncCapability, TextDocumentSyncKind,9 TextDocumentSyncOptions, Url, WorkDoneProgressOptions,10};1112fn main() {13 let mut log = File::create("test").unwrap();14 writeln!(log, "start").unwrap();15 let (connection, io_threads) = Connection::stdio();16 let capabilities = serde_json::to_value(&ServerCapabilities {17 completion_provider: Some(CompletionOptions::default()),18 definition_provider: Some(lsp_types::OneOf::Left(true)),19 document_link_provider: Some(DocumentLinkOptions {20 resolve_provider: Some(false),21 work_done_progress_options: WorkDoneProgressOptions::default(),22 }),23 hover_provider: Some(lsp_types::HoverProviderCapability::Simple(true)),24 text_document_sync: Some(TextDocumentSyncCapability::Options(25 TextDocumentSyncOptions {26 change: Some(TextDocumentSyncKind::FULL),27 open_close: Some(true),28 ..TextDocumentSyncOptions::default()29 },30 )),31 ..ServerCapabilities::default()32 })33 .expect("failed to convert capabilities to json");3435 connection36 .initialize(capabilities)37 .expect("failed to initialize connection");3839 writeln!(log, "initialized").unwrap();4041 main_loop(&mut log, &connection).expect("main loop failed");4243 io_threads.join().expect("failed to join io_threads");44}45fn main_loop(log: &mut File, connection: &Connection) -> anyhow::Result<()> {46 47 4849 let reply = |response: Response| {50 connection51 .sender52 .send(Message::Response(response))53 .expect("failed to respond");54 };5556 for msg in &connection.receiver {57 match msg {58 Message::Response(_) => (),59 Message::Request(req) => {60 if connection.handle_shutdown(&req)? {61 return Ok(());62 }63 if let Some((id, params)) = cast::<DocumentLinkRequest>(&req) {64 reply(Response::new_ok(id, <Vec<DocumentLink>>::new()));65 } else if let Some((id, params)) = cast::<HoverRequest>(&req) {66 let pos = params67 .text_document_position_params68 .text_document69 .uri70 .path();71 let buf = PathBuf::from_str(pos).unwrap();72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 } else {102 reply(Response::new_err(103 req.id,104 ErrorCode::MethodNotFound as i32,105 format!("unrecognized request {}", req.method),106 ))107 }108 109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 }143 Message::Notification(req) => {144 let mut handle = |text: String, uri: Url| {145 writeln!(log, "updated file: {:?}", uri).unwrap();146 let path = match PathBuf::from_str(uri.path()) {147 Ok(x) => x,148 Err(_) => return,149 };150 let (ast, errors) = jrsonnet_rowan_parser::parse(&text);151 152 153 writeln!(log, "parsed: {:?}", uri).unwrap();154 };155156 match &*req.method {157 DidOpenTextDocument::METHOD => {158 let params: DidOpenTextDocumentParams =159 match serde_json::from_value(req.params) {160 Ok(x) => x,161 Err(_) => continue,162 };163 handle(params.text_document.text, params.text_document.uri);164 }165 DidChangeTextDocument::METHOD => {166 let params: DidChangeTextDocumentParams =167 match serde_json::from_value(req.params) {168 Ok(x) => x,169 Err(_) => continue,170 };171 for change in params.content_changes.into_iter() {172 handle(change.text, params.text_document.uri.clone());173 }174 }175 _ => continue,176 }177 }178 }179 }180 Ok(())181}182fn cast<R>(req: &Request) -> Option<(RequestId, R::Params)>183where184 R: lsp_types::request::Request,185 R::Params: serde::de::DeserializeOwned,186{187 req.clone().extract(R::METHOD).ok()188}