A simple CPU rendered GUI IDE experience.
call hierarchy etc
bendn 4 days ago
parent 6e48bb5 · commit 01a6fdf
-rw-r--r--src/commands.rs24
-rw-r--r--src/edi/input_handlers/keyboard.rs32
-rw-r--r--src/edi/lsp_impl.rs37
-rw-r--r--src/gotolist.rs42
-rw-r--r--src/lsp/client.rs61
-rw-r--r--src/text.rs4
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;