1use std::{2 collections::HashMap,3 fs::File,4 path::{Path, PathBuf},5 str::FromStr,6};78use jrsonnet_evaluator::{EvaluationState, FileImportResolver, Val};9use jrsonnet_parser::{ExprLocation, ParserSettings};10use lsp_server::{Connection, ErrorCode, Message, Request, RequestId, Response};11use lsp_types::{12 notification::{DidChangeTextDocument, DidOpenTextDocument, Notification},13 request::{DocumentLinkRequest, HoverRequest},14 CompletionOptions, DidChangeTextDocumentParams, DidOpenTextDocumentParams, DocumentLink,15 DocumentLinkOptions, Hover, HoverContents, MarkupContent, MarkupKind, ServerCapabilities,16 TextDocumentSyncCapability, TextDocumentSyncKind, TextDocumentSyncOptions, Url,17 WorkDoneProgressOptions,18};1920use std::io::Write;2122fn main() {23 let mut log = File::create("test").unwrap();24 writeln!(log, "start").unwrap();25 let (connection, io_threads) = Connection::stdio();26 let capabilities = serde_json::to_value(&ServerCapabilities {27 completion_provider: Some(CompletionOptions::default()),28 definition_provider: Some(lsp_types::OneOf::Left(true)),29 document_link_provider: Some(DocumentLinkOptions {30 resolve_provider: Some(false),31 work_done_progress_options: WorkDoneProgressOptions::default(),32 }),33 hover_provider: Some(lsp_types::HoverProviderCapability::Simple(true)),34 text_document_sync: Some(TextDocumentSyncCapability::Options(35 TextDocumentSyncOptions {36 change: Some(TextDocumentSyncKind::FULL),37 open_close: Some(true),38 ..TextDocumentSyncOptions::default()39 },40 )),41 ..ServerCapabilities::default()42 })43 .expect("failed to convert capabilities to json");4445 connection46 .initialize(capabilities)47 .expect("failed to initialize connection");4849 writeln!(log, "initialized").unwrap();5051 main_loop(&mut log, &connection).expect("main loop failed");5253 io_threads.join().expect("failed to join io_threads");54}55fn main_loop(log: &mut File, connection: &Connection) -> anyhow::Result<()> {56 let mut es = EvaluationState::default();57 es.set_import_resolver(Box::new(FileImportResolver::default()));5859 let reply = |response: Response| {60 connection61 .sender62 .send(Message::Response(response))63 .expect("failed to respond");64 };6566 for msg in &connection.receiver {67 match msg {68 Message::Response(_) => (),69 Message::Request(req) => {70 if connection.handle_shutdown(&req)? {71 return Ok(());72 }73 if let Some((id, params)) = cast::<DocumentLinkRequest>(&req) {74 reply(Response::new_ok(id, <Vec<DocumentLink>>::new()));75 } else if let Some((id, params)) = cast::<HoverRequest>(&req) {76 let pos = params77 .text_document_position_params78 .text_document79 .uri80 .path();81 let buf = PathBuf::from_str(pos).unwrap();82 let pos = es83 .map_from_source_location(84 &buf,85 params.text_document_position_params.position.line as usize + 1,86 params.text_document_position_params.position.character as usize + 1,87 )88 .unwrap();89 let el = ExprLocation(buf.clone().into(), pos as usize, pos as usize);90 let es2 = es.clone();91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 } else112 113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 {147 reply(Response::new_err(148 req.id,149 ErrorCode::MethodNotFound as i32,150 format!("unrecognized request {}", req.method),151 ))152 }153 }154 Message::Notification(req) => {155 let mut handle = |text: String, uri: Url| {156 writeln!(log, "updated file: {:?}", uri).unwrap();157 let path = match PathBuf::from_str(uri.path()) {158 Ok(x) => x,159 Err(_) => return,160 };161 let parsed = match jrsonnet_parser::parse(162 &text,163 &ParserSettings {164 file_name: path.clone().into(),165 },166 ) {167 Ok(v) => v,168 Err(e) => {169 writeln!(log, "fuck D: {:?}", e).unwrap();170 return;171 172 }173 };174 es.add_parsed_file(path.into(), text.into(), parsed)175 .unwrap();176 writeln!(log, "parsed: {:?}", uri).unwrap();177 };178179 match &*req.method {180 DidOpenTextDocument::METHOD => {181 let params: DidOpenTextDocumentParams =182 match serde_json::from_value(req.params) {183 Ok(x) => x,184 Err(_) => continue,185 };186 handle(params.text_document.text, params.text_document.uri);187 }188 DidChangeTextDocument::METHOD => {189 let params: DidChangeTextDocumentParams =190 match serde_json::from_value(req.params) {191 Ok(x) => x,192 Err(_) => continue,193 };194 for change in params.content_changes.into_iter() {195 handle(change.text, params.text_document.uri.clone());196 }197 }198 _ => continue,199 }200 }201 }202 }203 Ok(())204}205fn cast<R>(req: &Request) -> Option<(RequestId, R::Params)>206where207 R: lsp_types::request::Request,208 R::Params: serde::de::DeserializeOwned,209{210 req.clone().extract(R::METHOD).ok()211}