aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/assists.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api/src/assists.rs')
-rw-r--r--crates/ra_ide_api/src/assists.rs89
1 files changed, 89 insertions, 0 deletions
diff --git a/crates/ra_ide_api/src/assists.rs b/crates/ra_ide_api/src/assists.rs
new file mode 100644
index 000000000..2da251df5
--- /dev/null
+++ b/crates/ra_ide_api/src/assists.rs
@@ -0,0 +1,89 @@
1mod fill_match_arm;
2
3use ra_syntax::{
4 TextRange, SourceFile, AstNode,
5 algo::find_node_at_offset,
6};
7use ra_ide_api_light::{
8 LocalEdit,
9 assists::{
10 Assist,
11 AssistBuilder
12 }
13};
14use crate::{
15 db::RootDatabase,
16 FileId
17};
18
19/// Return all the assists applicable at the given position.
20pub(crate) fn assists(
21 db: &RootDatabase,
22 file_id: FileId,
23 file: &SourceFile,
24 range: TextRange,
25) -> Vec<LocalEdit> {
26 let ctx = AssistCtx::new(db, file_id, file, range);
27 [fill_match_arm::fill_match_arm]
28 .iter()
29 .filter_map(|&assist| ctx.clone().apply(assist))
30 .collect()
31}
32
33#[derive(Debug, Clone)]
34pub struct AssistCtx<'a> {
35 file_id: FileId,
36 source_file: &'a SourceFile,
37 db: &'a RootDatabase,
38 range: TextRange,
39 should_compute_edit: bool,
40}
41
42impl<'a> AssistCtx<'a> {
43 pub(crate) fn new(
44 db: &'a RootDatabase,
45 file_id: FileId,
46 source_file: &'a SourceFile,
47 range: TextRange,
48 ) -> AssistCtx<'a> {
49 AssistCtx {
50 source_file,
51 file_id,
52 db,
53 range,
54 should_compute_edit: false,
55 }
56 }
57
58 pub fn apply(mut self, assist: fn(AssistCtx) -> Option<Assist>) -> Option<LocalEdit> {
59 self.should_compute_edit = true;
60 match assist(self) {
61 None => None,
62 Some(Assist::Edit(e)) => Some(e),
63 Some(Assist::Applicable) => unreachable!(),
64 }
65 }
66
67 #[allow(unused)]
68 pub fn check(mut self, assist: fn(AssistCtx) -> Option<Assist>) -> bool {
69 self.should_compute_edit = false;
70 match assist(self) {
71 None => false,
72 Some(Assist::Edit(_)) => unreachable!(),
73 Some(Assist::Applicable) => true,
74 }
75 }
76
77 fn build(self, label: impl Into<String>, f: impl FnOnce(&mut AssistBuilder)) -> Option<Assist> {
78 if !self.should_compute_edit {
79 return Some(Assist::Applicable);
80 }
81 let mut edit = AssistBuilder::default();
82 f(&mut edit);
83 Some(edit.build(label))
84 }
85
86 pub(crate) fn node_at_offset<N: AstNode>(&self) -> Option<&'a N> {
87 find_node_at_offset(self.source_file.syntax(), self.range.start())
88 }
89}