A simple CPU rendered GUI IDE experience.
| -rw-r--r-- | src/commands.rs | 24 | ||||
| -rw-r--r-- | src/edi/input_handlers/keyboard.rs | 32 | ||||
| -rw-r--r-- | src/edi/lsp_impl.rs | 37 | ||||
| -rw-r--r-- | src/gotolist.rs | 42 | ||||
| -rw-r--r-- | src/lsp/client.rs | 61 | ||||
| -rw-r--r-- | src/text.rs | 4 |
6 files changed, 175 insertions, 25 deletions
diff --git a/src/commands.rs b/src/commands.rs index edcf6d6..1273cfe 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -111,6 +111,10 @@ commands!( @ RARunTest: "run-test", /// Go to the references to this symbol @ References: "references", + /// Incoming callers of this function + @ Incoming: "callers-of", + /// Functions this function calls + @ Outgoing: "calling", // /// View child modules // @ ViewChildModules: "child-modules", /// GoTo line, @@ -410,6 +414,26 @@ impl Editor { ), ..default() }), + Cmd::Incoming => { + let x = l.runtime.spawn(l.callers(tdpp!(self))); + self.state = crate::edi::st::State::GoToL(GoToList { + data: ( + vec![], + Some(crate::gotolist::O::Incoming(Rq::new(x))), + ), + ..default() + }); + } + Cmd::Outgoing => { + let x = l.runtime.spawn(l.calling(tdpp!(self))); + self.state = crate::edi::st::State::GoToL(GoToList { + data: ( + vec![], + Some(crate::gotolist::O::Outgoing(Rq::new(x))), + ), + ..default() + }); + } _ => unimplemented!(), } Ok(()) diff --git a/src/edi/input_handlers/keyboard.rs b/src/edi/input_handlers/keyboard.rs index e1587e8..48f91d6 100644 --- a/src/edi/input_handlers/keyboard.rs +++ b/src/edi/input_handlers/keyboard.rs @@ -278,14 +278,14 @@ impl Editor { Some(Do::GoToMatch) if let Some(x) = &self.requests.document_highlights.result => - { + 'out: { let lc = &self .text .cursor .iter() .max_by_key(|x| x.position) .unwrap(); - let n = x + let Some((p_, n)) = x .iter() .zip(0..) .filter_map_at::<0>(|x| self.text.l_range(x.range)) @@ -293,16 +293,24 @@ impl Editor { x.contains(lc) })) .max_by_key(|x| x.0.start) - .unwrap() - .1; - - let p = self - .text - .l_position(x[(n + 1) % x.len()].range.start) - .unwrap(); - self.text.scroll_to(p); - if !self.text.cursor.iter().any(|x| *x == p) { - self.text.cursor.add(p, &self.text.rope); + else { + self.bar.last_action = + "couldnt get symbol here".into(); + break 'out; + }; + if self.text.cursor.inner.len() == 1 + && self.text.cursor.first() != p_.start + { + self.text.cursor.just(p_.start, &self.text.rope); + } else { + let p = self + .text + .l_position(x[(n + 1) % x.len()].range.start) + .unwrap(); + self.text.scroll_to(p); + if !self.text.cursor.iter().any(|x| *x == p) { + self.text.cursor.add(p, &self.text.rope); + } } } Some(Do::GoToMatch) => diff --git a/src/edi/lsp_impl.rs b/src/edi/lsp_impl.rs index f7e617b..19ad79b 100644 --- a/src/edi/lsp_impl.rs +++ b/src/edi/lsp_impl.rs @@ -86,7 +86,12 @@ impl crate::edi::Editor { self.text.set_inlay(x); }) }); - self.requests.document_highlights.poll(|x, _| x.ok()); + self.requests.document_highlights.poll(|x, _| { + x.ok().map(|mut x| { + x.sort_unstable_by_key(|x| x.range.start); + x + }) + }); self.requests.diag.poll(|x, _| x.ok().flatten()); if let CompletionState::Complete(rq) = &mut self.requests.complete { @@ -190,7 +195,35 @@ impl crate::edi::Editor { }) }); } - _ => {} + Some(crate::gotolist::O::Bmk) => {} + Some(crate::gotolist::O::Incoming(x)) => { + x.poll(|x, _| { + let x = x.ok()?; + z.data.0 = x + .into_iter() + .map(|x| { + let y = Some(x.from.name.clone()); + (GoTo::from(x), y) + }) + .collect(); + Some(()) + }); + } + Some(crate::gotolist::O::Outgoing(x)) => { + x.poll(|x, _| { + let x = x.ok()?; + z.data.0 = x + .into_iter() + .map(|x| { + let y = Some(x.to.name.clone()); + (GoTo::from(x), y) + }) + .collect(); + Some(()) + }); + } + + None => {} }, _ => {} } diff --git a/src/gotolist.rs b/src/gotolist.rs index 450e486..1268dec 100644 --- a/src/gotolist.rs +++ b/src/gotolist.rs @@ -4,10 +4,13 @@ use std::path::Path; use dsb::Cell; use dsb::cell::Style; use lsp_types::request::GotoImplementation; -use lsp_types::{Location, LocationLink, Range}; +use lsp_types::{ + CallHierarchyIncomingCall, CallHierarchyOutgoingCall, Location, + LocationLink, Range, +}; use crate::FG; -use crate::lsp::RqS; +use crate::lsp::{Rq, RqS}; use crate::menu::Key; use crate::menu::generic::{GenericMenu, MenuData}; use crate::rnd::simplify_path; @@ -18,6 +21,12 @@ pub enum GTL {} pub enum O { Impl(RqS<(), GotoImplementation>), References(RqS<(), lsp_types::request::References>), + Incoming( + Rq<(), Vec<CallHierarchyIncomingCall>, (), rootcause::Report>, + ), + Outgoing( + Rq<(), Vec<CallHierarchyOutgoingCall>, (), rootcause::Report>, + ), Bmk, } impl<'a> Key<'a> for (GoTo<'a>, Option<&'a str>) { @@ -37,12 +46,7 @@ impl MenuData for GTL { x: &'a Self::Data, ) -> impl Iterator<Item = Self::Element<'a>> { use ttools::*; - x.0.iter() - // .map(|x| { - // x - // }) - .map_at::<0>(GoTo::asref) - .map_at::<1>(Option::as_deref) + x.0.iter().map_all((GoTo::asref, Option::as_deref)) } fn r( @@ -67,6 +71,7 @@ impl MenuData for GTL { desc.map(str::chars) .into_iter() .flatten() + .chain([' ']) .chain( simplify_path( &elem @@ -132,7 +137,26 @@ impl From<&LocationLink> for GoTo<'static> { } } } - +impl From<CallHierarchyIncomingCall> for GoTo<'static> { + fn from( + CallHierarchyIncomingCall { from, from_ranges }: CallHierarchyIncomingCall, + ) -> Self { + Self { + path: from.uri.to_file_path().unwrap().into(), + at: At::R(from_ranges[0]), + } + } +} +impl From<CallHierarchyOutgoingCall> for GoTo<'static> { + fn from( + CallHierarchyOutgoingCall { to, from_ranges }: CallHierarchyOutgoingCall, + ) -> Self { + Self { + path: to.uri.to_file_path().unwrap().into(), + at: At::R(from_ranges[0]), + } + } +} #[derive(Debug, Eq, PartialEq, Clone, Copy)] pub enum At { R(Range), diff --git a/src/lsp/client.rs b/src/lsp/client.rs index 2650b5f..4b7b85f 100644 --- a/src/lsp/client.rs +++ b/src/lsp/client.rs @@ -14,9 +14,11 @@ use lsp_server::{ use lsp_types::notification::*; use lsp_types::request::*; use lsp_types::*; +use rootcause::option_ext::OptionExt; use rust_analyzer::lsp::ext::*; use tokio::sync::oneshot; use ttools::*; +use winit::platform::x11::ffi::BadImplementation; use crate::lsp::BehaviourAfter::{self, *}; use crate::lsp::init_opts::ra_config; @@ -586,6 +588,65 @@ impl Client { ) .unwrap(); } + pub fn find_function( + &self, + at: TextDocumentPositionParams, + ) -> Result< + impl Future< + Output = Result< + Option<CallHierarchyItem>, + RequestError<CallHierarchyPrepare>, + >, + >, + SendError<Message>, + > { + self.request::<CallHierarchyPrepare>(&CallHierarchyPrepareParams { + text_document_position_params: at, + work_done_progress_params: default(), + }) + .map(fst) + .map(|x| x.map(|x| x.map(|x| x.and_then(|mut x| x.try_remove(0))))) + } + pub async fn callers( + &self, + at: TextDocumentPositionParams, + ) -> rootcause::Result<Vec<CallHierarchyIncomingCall>> { + let calls = self + .request::<CallHierarchyIncomingCalls>( + &CallHierarchyIncomingCallsParams { + item: self + .find_function(at)? + .await? + .context("no chi")?, + work_done_progress_params: default(), + partial_result_params: default(), + }, + )? + .0 + .await? + .context("Couldnt find incoming calls")?; + Ok(calls) + } + pub async fn calling( + &self, + at: TextDocumentPositionParams, + ) -> rootcause::Result<Vec<CallHierarchyOutgoingCall>> { + let calls = self + .request::<CallHierarchyOutgoingCalls>( + &CallHierarchyOutgoingCallsParams { + item: self + .find_function(at)? + .await? + .context("no chi")?, + work_done_progress_params: default(), + partial_result_params: default(), + }, + )? + .0 + .await? + .context("Couldnt find incoming calls")?; + Ok(calls) + } } pub trait PathURI { diff --git a/src/text.rs b/src/text.rs index c469042..bc4da13 100644 --- a/src/text.rs +++ b/src/text.rs @@ -16,8 +16,8 @@ use helix_core::Syntax; use helix_core::syntax::{HighlightEvent, Loader}; use implicit_fn::implicit_fn; use lsp_types::{ - DocumentSymbol, Location, SemanticTokensLegend, - SnippetTextEdit, TextEdit, + DocumentSymbol, Location, SemanticTokensLegend, SnippetTextEdit, + TextEdit, }; pub use manipulations::Manip; use rootcause::option_ext::OptionExt; |