git.delta.rocks / jrsonnet / refs/commits / b1b8b4cf86ba

difftreelog

source

jrsonnet-lsp/src/main.rs6.4 KiBsourcehistory
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				// reply(Response::new_ok(92				// 	id,93				// 	Some(Hover {94				// 		range: None,95				// 		contents: HoverContents::Markup(MarkupContent {96				// 			kind: MarkupKind::Markdown,97				// 			value: es98				// 				.run_in_state_with_breakpoint(el, move || {99				// 					es2.reset_evaluation_state(&buf);100				// 					es2.import_file(&PathBuf::new(), &buf)?101				// 						.to_string()102				// 						.map(|_| ())103				// 				})104				// 				.unwrap()105				// 				.unwrap_or_else(|| Val::Null)106				// 				.value_type()107				// 				.to_string(),108				// 		}),109				// 	}),110				// ));111				} else112				/*113				if let Some((id, params)) = cast::<DocumentLinkRequest>(&req) {114					 let links = handle_links(&files, params).unwrap_or_default();115					 reply(Response::new_ok(id, links));116				} else if let Some((id, params)) = cast::<GotoDefinition>(&req) {117					 if let Some(loc) = handle_goto(&files, params) {118						  reply(Response::new_ok(id, loc))119					 } else {120						  reply(Response::new_ok(id, ()))121					 }122				} else if let Some((id, params)) = cast::<HoverRequest>(&req) {123					 match handle_hover(&files, params) {124						  Some((range, markdown)) => {125								reply(Response::new_ok(126									 id,127									 Hover {128										  contents: HoverContents::Markup(MarkupContent {129												kind: MarkupKind::Markdown,130												value: markdown,131										  }),132										  range,133									 },134								));135						  }136						  None => {137								reply(Response::new_ok(id, ()));138						  }139					 }140				} else if let Some((id, params)) = cast::<Completion>(&req) {141					 let completions = handle_completion(&files, params.text_document_position)142						  .unwrap_or_default();143					 reply(Response::new_ok(id, completions));144				} else145				*/146				{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							// connection.sender.send(Message::Notification(Notification::new_err(req.id, ErrorCode::ParseError as i32, format!("Fuck D: {:?}", e))))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}