aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src/lib.rs
diff options
context:
space:
mode:
authorvsrs <[email protected]>2020-05-08 17:34:34 +0100
committervsrs <[email protected]>2020-05-08 17:34:34 +0100
commit0ef17ef1ee9fb0ce7149176d12f4d225f6d01401 (patch)
treefa2f168120f36f8dbef5dc1e85fea0c0071639c2 /crates/ra_assists/src/lib.rs
parent1be6320ea6cf7830195f80681fa0f43cc340da7e (diff)
parentd3eb9d8eafbebca7da95fa8a4813b92eb5080500 (diff)
Merge remote-tracking branch 'upstream/master' into uniformed_debug_lens
# Conflicts: # editors/code/src/commands/runnables.ts
Diffstat (limited to 'crates/ra_assists/src/lib.rs')
-rw-r--r--crates/ra_assists/src/lib.rs124
1 files changed, 51 insertions, 73 deletions
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index f4f37614f..b6dc7cb1b 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -10,7 +10,7 @@ macro_rules! eprintln {
10 ($($tt:tt)*) => { stdx::eprintln!($($tt)*) }; 10 ($($tt:tt)*) => { stdx::eprintln!($($tt)*) };
11} 11}
12 12
13mod assist_ctx; 13mod assist_context;
14mod marks; 14mod marks;
15#[cfg(test)] 15#[cfg(test)]
16mod tests; 16mod tests;
@@ -18,20 +18,22 @@ pub mod utils;
18pub mod ast_transform; 18pub mod ast_transform;
19 19
20use hir::Semantics; 20use hir::Semantics;
21use ra_db::{FileId, FileRange}; 21use ra_db::FileRange;
22use ra_ide_db::RootDatabase; 22use ra_ide_db::{source_change::SourceChange, RootDatabase};
23use ra_syntax::{TextRange, TextSize}; 23use ra_syntax::TextRange;
24use ra_text_edit::TextEdit;
25 24
26pub(crate) use crate::assist_ctx::{Assist, AssistCtx}; 25pub(crate) use crate::assist_context::{AssistContext, Assists};
27 26
28/// Unique identifier of the assist, should not be shown to the user 27/// Unique identifier of the assist, should not be shown to the user
29/// directly. 28/// directly.
30#[derive(Debug, Clone, Copy, PartialEq, Eq)] 29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub struct AssistId(pub &'static str); 30pub struct AssistId(pub &'static str);
32 31
32#[derive(Clone, Debug)]
33pub struct GroupLabel(pub String);
34
33#[derive(Debug, Clone)] 35#[derive(Debug, Clone)]
34pub struct AssistLabel { 36pub struct Assist {
35 pub id: AssistId, 37 pub id: AssistId,
36 /// Short description of the assist, as shown in the UI. 38 /// Short description of the assist, as shown in the UI.
37 pub label: String, 39 pub label: String,
@@ -41,93 +43,69 @@ pub struct AssistLabel {
41 pub target: TextRange, 43 pub target: TextRange,
42} 44}
43 45
44#[derive(Clone, Debug)] 46#[derive(Debug, Clone)]
45pub struct GroupLabel(pub String); 47pub struct ResolvedAssist {
48 pub assist: Assist,
49 pub source_change: SourceChange,
50}
51
52impl Assist {
53 /// Return all the assists applicable at the given position.
54 ///
55 /// Assists are returned in the "unresolved" state, that is only labels are
56 /// returned, without actual edits.
57 pub fn unresolved(db: &RootDatabase, range: FileRange) -> Vec<Assist> {
58 let sema = Semantics::new(db);
59 let ctx = AssistContext::new(sema, range);
60 let mut acc = Assists::new_unresolved(&ctx);
61 handlers::all().iter().for_each(|handler| {
62 handler(&mut acc, &ctx);
63 });
64 acc.finish_unresolved()
65 }
66
67 /// Return all the assists applicable at the given position.
68 ///
69 /// Assists are returned in the "resolved" state, that is with edit fully
70 /// computed.
71 pub fn resolved(db: &RootDatabase, range: FileRange) -> Vec<ResolvedAssist> {
72 let sema = Semantics::new(db);
73 let ctx = AssistContext::new(sema, range);
74 let mut acc = Assists::new_resolved(&ctx);
75 handlers::all().iter().for_each(|handler| {
76 handler(&mut acc, &ctx);
77 });
78 acc.finish_resolved()
79 }
46 80
47impl AssistLabel {
48 pub(crate) fn new( 81 pub(crate) fn new(
49 id: AssistId, 82 id: AssistId,
50 label: String, 83 label: String,
51 group: Option<GroupLabel>, 84 group: Option<GroupLabel>,
52 target: TextRange, 85 target: TextRange,
53 ) -> AssistLabel { 86 ) -> Assist {
54 // FIXME: make fields private, so that this invariant can't be broken 87 // FIXME: make fields private, so that this invariant can't be broken
55 assert!(label.starts_with(|c: char| c.is_uppercase())); 88 assert!(label.starts_with(|c: char| c.is_uppercase()));
56 AssistLabel { id, label, group, target } 89 Assist { id, label, group, target }
57 }
58}
59
60#[derive(Debug, Clone)]
61pub struct AssistAction {
62 pub edit: TextEdit,
63 pub cursor_position: Option<TextSize>,
64 pub file: AssistFile,
65}
66
67#[derive(Debug, Clone)]
68pub struct ResolvedAssist {
69 pub label: AssistLabel,
70 pub action: AssistAction,
71}
72
73#[derive(Debug, Clone, Copy)]
74pub enum AssistFile {
75 CurrentFile,
76 TargetFile(FileId),
77}
78
79impl Default for AssistFile {
80 fn default() -> Self {
81 Self::CurrentFile
82 } 90 }
83} 91}
84 92
85/// Return all the assists applicable at the given position.
86///
87/// Assists are returned in the "unresolved" state, that is only labels are
88/// returned, without actual edits.
89pub fn unresolved_assists(db: &RootDatabase, range: FileRange) -> Vec<AssistLabel> {
90 let sema = Semantics::new(db);
91 let ctx = AssistCtx::new(&sema, range, false);
92 handlers::all()
93 .iter()
94 .filter_map(|f| f(ctx.clone()))
95 .flat_map(|it| it.0)
96 .map(|a| a.label)
97 .collect()
98}
99
100/// Return all the assists applicable at the given position.
101///
102/// Assists are returned in the "resolved" state, that is with edit fully
103/// computed.
104pub fn resolved_assists(db: &RootDatabase, range: FileRange) -> Vec<ResolvedAssist> {
105 let sema = Semantics::new(db);
106 let ctx = AssistCtx::new(&sema, range, true);
107 let mut a = handlers::all()
108 .iter()
109 .filter_map(|f| f(ctx.clone()))
110 .flat_map(|it| it.0)
111 .map(|it| it.into_resolved().unwrap())
112 .collect::<Vec<_>>();
113 a.sort_by_key(|it| it.label.target.len());
114 a
115}
116
117mod handlers { 93mod handlers {
118 use crate::{Assist, AssistCtx}; 94 use crate::{AssistContext, Assists};
119 95
120 pub(crate) type Handler = fn(AssistCtx) -> Option<Assist>; 96 pub(crate) type Handler = fn(&mut Assists, &AssistContext) -> Option<()>;
121 97
122 mod add_custom_impl; 98 mod add_custom_impl;
123 mod add_derive; 99 mod add_derive;
124 mod add_explicit_type; 100 mod add_explicit_type;
101 mod add_from_impl_for_enum;
125 mod add_function; 102 mod add_function;
126 mod add_impl; 103 mod add_impl;
127 mod add_missing_impl_members; 104 mod add_missing_impl_members;
128 mod add_new; 105 mod add_new;
129 mod apply_demorgan; 106 mod apply_demorgan;
130 mod auto_import; 107 mod auto_import;
108 mod change_return_type_to_result;
131 mod change_visibility; 109 mod change_visibility;
132 mod early_return; 110 mod early_return;
133 mod fill_match_arms; 111 mod fill_match_arms;
@@ -144,13 +122,12 @@ mod handlers {
144 mod raw_string; 122 mod raw_string;
145 mod remove_dbg; 123 mod remove_dbg;
146 mod remove_mut; 124 mod remove_mut;
125 mod reorder_fields;
147 mod replace_if_let_with_match; 126 mod replace_if_let_with_match;
148 mod replace_let_with_if_let; 127 mod replace_let_with_if_let;
149 mod replace_qualified_name_with_use; 128 mod replace_qualified_name_with_use;
150 mod replace_unwrap_with_match; 129 mod replace_unwrap_with_match;
151 mod split_import; 130 mod split_import;
152 mod add_from_impl_for_enum;
153 mod reorder_fields;
154 mod unwrap_block; 131 mod unwrap_block;
155 132
156 pub(crate) fn all() -> &'static [Handler] { 133 pub(crate) fn all() -> &'static [Handler] {
@@ -165,6 +142,7 @@ mod handlers {
165 add_new::add_new, 142 add_new::add_new,
166 apply_demorgan::apply_demorgan, 143 apply_demorgan::apply_demorgan,
167 auto_import::auto_import, 144 auto_import::auto_import,
145 change_return_type_to_result::change_return_type_to_result,
168 change_visibility::change_visibility, 146 change_visibility::change_visibility,
169 early_return::convert_to_guarded_return, 147 early_return::convert_to_guarded_return,
170 fill_match_arms::fill_match_arms, 148 fill_match_arms::fill_match_arms,