diff options
Diffstat (limited to 'crates/ra_ide_api/src/assists.rs')
-rw-r--r-- | crates/ra_ide_api/src/assists.rs | 109 |
1 files changed, 22 insertions, 87 deletions
diff --git a/crates/ra_ide_api/src/assists.rs b/crates/ra_ide_api/src/assists.rs index 2da251df5..2a96fdf47 100644 --- a/crates/ra_ide_api/src/assists.rs +++ b/crates/ra_ide_api/src/assists.rs | |||
@@ -1,89 +1,24 @@ | |||
1 | mod fill_match_arm; | 1 | use ra_db::{FileRange, FilePosition}; |
2 | 2 | ||
3 | use ra_syntax::{ | 3 | use crate::{SourceFileEdit, SourceChange, db::RootDatabase}; |
4 | TextRange, SourceFile, AstNode, | 4 | |
5 | algo::find_node_at_offset, | 5 | pub(crate) fn assists(db: &RootDatabase, frange: FileRange) -> Vec<SourceChange> { |
6 | }; | 6 | ra_assists::assists(db, frange) |
7 | use ra_ide_api_light::{ | 7 | .into_iter() |
8 | LocalEdit, | 8 | .map(|(label, action)| { |
9 | assists::{ | 9 | let file_id = frange.file_id; |
10 | Assist, | 10 | let file_edit = SourceFileEdit { |
11 | AssistBuilder | 11 | file_id, |
12 | } | 12 | edit: action.edit, |
13 | }; | 13 | }; |
14 | use crate::{ | 14 | SourceChange { |
15 | db::RootDatabase, | 15 | label: label.label, |
16 | FileId | 16 | source_file_edits: vec![file_edit], |
17 | }; | 17 | file_system_edits: vec![], |
18 | 18 | cursor_position: action | |
19 | /// Return all the assists applicable at the given position. | 19 | .cursor_position |
20 | pub(crate) fn assists( | 20 | .map(|offset| FilePosition { offset, file_id }), |
21 | db: &RootDatabase, | 21 | } |
22 | file_id: FileId, | 22 | }) |
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() | 23 | .collect() |
31 | } | 24 | } |
32 | |||
33 | #[derive(Debug, Clone)] | ||
34 | pub 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 | |||
42 | impl<'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 | } | ||