A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/edi/lsp_impl.rs')
| -rw-r--r-- | src/edi/lsp_impl.rs | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/src/edi/lsp_impl.rs b/src/edi/lsp_impl.rs new file mode 100644 index 0000000..c28670e --- /dev/null +++ b/src/edi/lsp_impl.rs @@ -0,0 +1,220 @@ +use lsp_server::Request as LRq; +use lsp_types::request::*; +use lsp_types::*; +use serde::{Deserialize, Serialize}; +use ttools::{Tupl, With}; + +use crate::complete::Complete; +use crate::edi::st::*; +use crate::hov::Hovr; +use crate::lsp::{RequestError, Rq}; +use crate::runnables::Runnables; +use crate::sym::GoTo; +use crate::{CompletionState, act, sig, sym}; + +#[derive(Default, Debug, Serialize, Deserialize)] +pub struct Requests { + pub hovering: + Rq<Hovr, Option<Hovr>, (usize, usize), RequestError<HoverRequest>>, + pub document_highlights: Rq< + Vec<DocumentHighlight>, + Vec<DocumentHighlight>, + (), + RequestError<DocumentHighlightRequest>, + >, + pub complete: CompletionState, + pub sig_help: Rq< + (SignatureHelp, usize, Option<usize>), + Option<SignatureHelp>, + (), + RequestError<SignatureHelpRequest>, + >, // vo, lines + // #[serde(serialize_with = "serialize_tokens")] + // #[serde(deserialize_with = "deserialize_tokens")] + #[serde(skip)] + pub semantic_tokens: Rq< + Box<[SemanticToken]>, + Box<[SemanticToken]>, + (), + RequestError<SemanticTokensFullRequest>, + >, + pub diag: Rq< + String, + Option<String>, + (), + RequestError<DocumentDiagnosticRequest>, + >, + #[serde(skip)] + pub inlay: Rq< + Vec<InlayHint>, + Vec<InlayHint>, + (), + RequestError<lsp_request!("textDocument/inlayHint")>, + >, + pub def: Rq< + LocationLink, + Option<GotoDefinitionResponse>, + (usize, usize), + RequestError<lsp_request!("textDocument/definition")>, + >, + #[serde(skip)] + pub document_symbols: Rq< + Option<Vec<DocumentSymbol>>, + Option<DocumentSymbolResponse>, + (), + RequestError<lsp_request!("textDocument/documentSymbol")>, + >, + #[serde(skip)] + pub git_diff: Rq<imara_diff::Diff, imara_diff::Diff, (), ()>, +} +impl crate::edi::Editor { + pub fn poll(&mut self) { + let Some((l, ..)) = self.lsp else { return }; + for rq in l.req_rx.try_iter() { + match rq { + LRq { method: "workspace/diagnostic/refresh", .. } => { + // let x = l.pull_diag(o.into(), diag.result.clone()); + // diag.request(l.runtime.spawn(x)); + } + rq => log::debug!("discarding request {rq:?}"), + } + } + self.requests.inlay.poll(|x, p| { + x.ok().or(p.1).inspect(|x| { + self.text.set_inlay(x); + }) + }); + self.requests.document_highlights.poll(|x, _| x.ok()); + self.requests.diag.poll(|x, _| x.ok().flatten()); + if let CompletionState::Complete(rq) = &mut self.requests.complete + { + rq.poll(|f, (c, _)| { + f.ok().flatten().map(|x| Complete { + r: x, + start: c, + selection: 0, + vo: 0, + }) + }); + }; + match &mut self.state { + State::Symbols(x) => { + x.poll(|x, (_, p)| { + let Some(p) = p else { unreachable!() }; + + x.ok().flatten().map(|r| sym::Symbols { + data: r.with(p.data.drop::<1>()), + selection: 0, + vo: 0, + ..p + }) + }); + } + State::CodeAction(x) => { + if x.poll(|x, _| { + let lems: Vec<CodeAction> = x + .ok()?? + .into_iter() + .map(|x| match x { + CodeActionOrCommand::CodeAction(x) => x, + _ => panic!("alas we dont like these"), + }) + .collect(); + if lems.is_empty() { + self.bar.last_action = + "no code actions available".into(); + None + } else { + self.bar.last_action = + format!("{} code actions", lems.len()); + Some(act::CodeActions::new(lems)) + } + }) && x.result.is_none() + { + self.state = State::Default; + } + } + State::Runnables(x) => { + x.poll(|x, ((), old)| { + Some(Runnables { + data: x.ok()?, + ..old.unwrap_or_default() + }) + }); + } + State::GoToL(z) => match &mut z.data.1 { + Some(crate::gotolist::O::References(y)) => { + y.poll(|x, _| { + x.ok().flatten().map(|x| { + z.data.0 = x.iter().map(GoTo::from).collect() + }) + }); + } + Some(crate::gotolist::O::Impl(y)) => { + y.poll(|x, _| { + x.ok().map(|x| { + x.and_then(|x| try { + z.data.0 = match x { + GotoDefinitionResponse::Scalar( + location, + ) => vec![GoTo::from( + location, + )], + GotoDefinitionResponse::Array( + locations, + ) => locations + .into_iter() + .map(GoTo::from) + .collect(), + GotoDefinitionResponse::Link( + location_links, + ) => location_links + .into_iter() + .map(|LocationLink {target_uri, target_range, .. }| { + GoTo::from( + Location { + uri: target_uri, + range: target_range, + } + ) + }) + .collect(), + }; + }); + }) + }); + } + _ => {} + }, + _ => {} + } + self.requests.def.poll(|x, _| { + x.ok().flatten().and_then(|x| match &x { + GotoDefinitionResponse::Link([x, ..]) => Some(x.clone()), + _ => None, + }) + }); + self.requests + .semantic_tokens + .poll(|x, _| x.ok().inspect(|x| self.text.set_toks(&x))); + self.requests.sig_help.poll(|x, ((), y)| { + x.ok().flatten().map(|x| { + if let Some((old_sig, vo, max)) = y + && &sig::active(&old_sig) == &sig::active(&x) + { + (x, vo, max) + } else { + (x, 0, None) + } + }) + }); + self.requests.hovering.poll(|x, _| x.ok().flatten()); + self.requests.git_diff.poll(|x, _| x.ok()); + self.requests.document_symbols.poll(|x, _| { + x.ok().flatten().map(|x| match x { + DocumentSymbolResponse::Flat(_) => None, + DocumentSymbolResponse::Nested(x) => Some(x), + }) + }); + } +} |