aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_editor/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_editor/src')
-rw-r--r--crates/ra_editor/src/code_actions.rs7
-rw-r--r--crates/ra_editor/src/lib.rs58
-rw-r--r--crates/ra_editor/src/typing.rs29
3 files changed, 71 insertions, 23 deletions
diff --git a/crates/ra_editor/src/code_actions.rs b/crates/ra_editor/src/code_actions.rs
index 1d78cb7e8..7615f37a6 100644
--- a/crates/ra_editor/src/code_actions.rs
+++ b/crates/ra_editor/src/code_actions.rs
@@ -12,6 +12,7 @@ use crate::{find_node_at_offset, TextEdit, TextEditBuilder};
12 12
13#[derive(Debug)] 13#[derive(Debug)]
14pub struct LocalEdit { 14pub struct LocalEdit {
15 pub label: String,
15 pub edit: TextEdit, 16 pub edit: TextEdit,
16 pub cursor_position: Option<TextUnit>, 17 pub cursor_position: Option<TextUnit>,
17} 18}
@@ -30,6 +31,7 @@ pub fn flip_comma<'a>(
30 edit.replace(prev.range(), next.text().to_string()); 31 edit.replace(prev.range(), next.text().to_string());
31 edit.replace(next.range(), prev.text().to_string()); 32 edit.replace(next.range(), prev.text().to_string());
32 LocalEdit { 33 LocalEdit {
34 label: "flip comma".to_string(),
33 edit: edit.finish(), 35 edit: edit.finish(),
34 cursor_position: None, 36 cursor_position: None,
35 } 37 }
@@ -58,6 +60,7 @@ pub fn add_derive<'a>(
58 Some(tt) => tt.syntax().range().end() - TextUnit::of_char(')'), 60 Some(tt) => tt.syntax().range().end() - TextUnit::of_char(')'),
59 }; 61 };
60 LocalEdit { 62 LocalEdit {
63 label: "add `#[derive]`".to_string(),
61 edit: edit.finish(), 64 edit: edit.finish(),
62 cursor_position: Some(offset), 65 cursor_position: Some(offset),
63 } 66 }
@@ -109,6 +112,7 @@ pub fn add_impl<'a>(
109 buf.push_str("\n}"); 112 buf.push_str("\n}");
110 edit.insert(start_offset, buf); 113 edit.insert(start_offset, buf);
111 LocalEdit { 114 LocalEdit {
115 label: "add impl".to_string(),
112 edit: edit.finish(), 116 edit: edit.finish(),
113 cursor_position: Some(offset), 117 cursor_position: Some(offset),
114 } 118 }
@@ -148,6 +152,7 @@ pub fn introduce_variable<'a>(
148 } 152 }
149 let cursor_position = anchor_stmt.range().start() + TextUnit::of_str("let "); 153 let cursor_position = anchor_stmt.range().start() + TextUnit::of_str("let ");
150 LocalEdit { 154 LocalEdit {
155 label: "introduce variable".to_string(),
151 edit: edit.finish(), 156 edit: edit.finish(),
152 cursor_position: Some(cursor_position), 157 cursor_position: Some(cursor_position),
153 } 158 }
@@ -194,6 +199,7 @@ pub fn make_pub_crate<'a>(
194 || parent.children().any(|child| child.kind() == VISIBILITY) 199 || parent.children().any(|child| child.kind() == VISIBILITY)
195 { 200 {
196 return LocalEdit { 201 return LocalEdit {
202 label: "make pub crate".to_string(),
197 edit: edit.finish(), 203 edit: edit.finish(),
198 cursor_position: Some(offset), 204 cursor_position: Some(offset),
199 }; 205 };
@@ -201,6 +207,7 @@ pub fn make_pub_crate<'a>(
201 207
202 edit.insert(node_start, "pub(crate) ".to_string()); 208 edit.insert(node_start, "pub(crate) ".to_string());
203 LocalEdit { 209 LocalEdit {
210 label: "make pub crate".to_string(),
204 edit: edit.finish(), 211 edit: edit.finish(),
205 cursor_position: Some(node_start), 212 cursor_position: Some(node_start),
206 } 213 }
diff --git a/crates/ra_editor/src/lib.rs b/crates/ra_editor/src/lib.rs
index 7a689b0f2..dcf8be5a7 100644
--- a/crates/ra_editor/src/lib.rs
+++ b/crates/ra_editor/src/lib.rs
@@ -42,6 +42,7 @@ pub struct Diagnostic {
42 pub range: TextRange, 42 pub range: TextRange,
43 pub msg: String, 43 pub msg: String,
44 pub severity: Severity, 44 pub severity: Severity,
45 pub fix: Option<LocalEdit>,
45} 46}
46 47
47#[derive(Debug)] 48#[derive(Debug)]
@@ -111,6 +112,7 @@ pub fn diagnostics(file: &SourceFileNode) -> Vec<Diagnostic> {
111 range: location_to_range(err.location()), 112 range: location_to_range(err.location()),
112 msg: format!("Syntax Error: {}", err), 113 msg: format!("Syntax Error: {}", err),
113 severity: Severity::Error, 114 severity: Severity::Error,
115 fix: None,
114 }) 116 })
115 .collect(); 117 .collect();
116 118
@@ -124,11 +126,30 @@ fn check_unnecessary_braces_in_use_statement(file: &SourceFileNode) -> Vec<Diagn
124 let mut diagnostics = Vec::new(); 126 let mut diagnostics = Vec::new();
125 for node in file.syntax().descendants() { 127 for node in file.syntax().descendants() {
126 if let Some(use_tree_list) = ast::UseTreeList::cast(node) { 128 if let Some(use_tree_list) = ast::UseTreeList::cast(node) {
127 if use_tree_list.use_trees().count() <= 1 { 129 if use_tree_list.use_trees().count() == 1 {
130 let range = use_tree_list.syntax().range();
131 // use_tree_list always has one child, so we use unwrap directly here.
132 let single_use_tree: ast::UseTree = use_tree_list.use_trees().next().unwrap();
133 let edit = text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(
134 single_use_tree,
135 )
136 .unwrap_or_else(|| {
137 let to_replace = single_use_tree.syntax().text().to_string();
138 let mut edit_builder = TextEditBuilder::new();
139 edit_builder.delete(range);
140 edit_builder.insert(range.start(), to_replace);
141 edit_builder.finish()
142 });
143
128 diagnostics.push(Diagnostic { 144 diagnostics.push(Diagnostic {
129 range: use_tree_list.syntax().range(), 145 range: range,
130 msg: format!("Unnecessary braces in use statement"), 146 msg: format!("Unnecessary braces in use statement"),
131 severity: Severity::WeakWarning, 147 severity: Severity::WeakWarning,
148 fix: Some(LocalEdit {
149 label: "Remove unnecessary braces".to_string(),
150 edit: edit,
151 cursor_position: None,
152 }),
132 }) 153 })
133 } 154 }
134 } 155 }
@@ -137,6 +158,28 @@ fn check_unnecessary_braces_in_use_statement(file: &SourceFileNode) -> Vec<Diagn
137 diagnostics 158 diagnostics
138} 159}
139 160
161fn text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(
162 single_use_tree: ast::UseTree,
163) -> Option<TextEdit> {
164 let use_tree_list_node = single_use_tree.syntax().parent()?;
165 if single_use_tree
166 .path()?
167 .segment()?
168 .syntax()
169 .first_child()?
170 .kind()
171 == SyntaxKind::SELF_KW
172 {
173 let start = use_tree_list_node.prev_sibling()?.range().start();
174 let end = use_tree_list_node.range().end();
175 let range = TextRange::from_to(start, end);
176 let mut edit_builder = TextEditBuilder::new();
177 edit_builder.delete(range);
178 return Some(edit_builder.finish());
179 }
180 None
181}
182
140pub fn syntax_tree(file: &SourceFileNode) -> String { 183pub fn syntax_tree(file: &SourceFileNode) -> String {
141 ::ra_syntax::utils::dump_tree(file.syntax()) 184 ::ra_syntax::utils::dump_tree(file.syntax())
142} 185}
@@ -173,8 +216,9 @@ pub fn find_node_at_offset<'a, N: AstNode<'a>>(
173 216
174#[cfg(test)] 217#[cfg(test)]
175mod tests { 218mod tests {
219 use crate::test_utils::{add_cursor, assert_eq_dbg, assert_eq_text, extract_offset};
220
176 use super::*; 221 use super::*;
177 use crate::test_utils::{add_cursor, assert_eq_dbg, extract_offset, assert_eq_text};
178 222
179 #[test] 223 #[test]
180 fn test_highlighting() { 224 fn test_highlighting() {
@@ -243,6 +287,7 @@ fn test_foo() {}
243use a; 287use a;
244use {b}; 288use {b};
245use a::{c}; 289use a::{c};
290use a::{self};
246use a::{c, d::e}; 291use a::{c, d::e};
247use a::{c, d::{e}}; 292use a::{c, d::{e}};
248fn main() {} 293fn main() {}
@@ -250,9 +295,10 @@ fn main() {}
250 ); 295 );
251 let diagnostics = check_unnecessary_braces_in_use_statement(&file); 296 let diagnostics = check_unnecessary_braces_in_use_statement(&file);
252 assert_eq_dbg( 297 assert_eq_dbg(
253 r#"[Diagnostic { range: [12; 15), msg: "Unnecessary braces in use statement", severity: WeakWarning }, 298 r#"[Diagnostic { range: [12; 15), msg: "Unnecessary braces in use statement", severity: WeakWarning, fix: Some(LocalEdit { label: "Remove unnecessary braces", edit: TextEdit { atoms: [AtomTextEdit { delete: [12; 12), insert: "b" }, AtomTextEdit { delete: [12; 15), insert: "" }] }, cursor_position: None }) },
254 Diagnostic { range: [24; 27), msg: "Unnecessary braces in use statement", severity: WeakWarning }, 299 Diagnostic { range: [24; 27), msg: "Unnecessary braces in use statement", severity: WeakWarning, fix: Some(LocalEdit { label: "Remove unnecessary braces", edit: TextEdit { atoms: [AtomTextEdit { delete: [24; 24), insert: "c" }, AtomTextEdit { delete: [24; 27), insert: "" }] }, cursor_position: None }) },
255 Diagnostic { range: [61; 64), msg: "Unnecessary braces in use statement", severity: WeakWarning }]"#, 300 Diagnostic { range: [36; 42), msg: "Unnecessary braces in use statement", severity: WeakWarning, fix: Some(LocalEdit { label: "Remove unnecessary braces", edit: TextEdit { atoms: [AtomTextEdit { delete: [34; 42), insert: "" }] }, cursor_position: None }) },
301 Diagnostic { range: [76; 79), msg: "Unnecessary braces in use statement", severity: WeakWarning, fix: Some(LocalEdit { label: "Remove unnecessary braces", edit: TextEdit { atoms: [AtomTextEdit { delete: [76; 76), insert: "e" }, AtomTextEdit { delete: [76; 79), insert: "" }] }, cursor_position: None }) }]"#,
256 &diagnostics, 302 &diagnostics,
257 ) 303 )
258 } 304 }
diff --git a/crates/ra_editor/src/typing.rs b/crates/ra_editor/src/typing.rs
index 5e412bcfa..f0d8dc7bb 100644
--- a/crates/ra_editor/src/typing.rs
+++ b/crates/ra_editor/src/typing.rs
@@ -8,7 +8,9 @@ use ra_syntax::{
8 SyntaxKind::*, 8 SyntaxKind::*,
9 SyntaxNodeRef, TextRange, TextUnit, 9 SyntaxNodeRef, TextRange, TextUnit,
10}; 10};
11use ra_text_edit::text_utils::contains_offset_nonstrict; 11use ra_text_edit::text_utils::{
12 contains_offset_nonstrict
13};
12 14
13use crate::{find_node_at_offset, TextEditBuilder, LocalEdit}; 15use crate::{find_node_at_offset, TextEditBuilder, LocalEdit};
14 16
@@ -19,6 +21,7 @@ pub fn join_lines(file: &SourceFileNode, range: TextRange) -> LocalEdit {
19 let pos = match text.find('\n') { 21 let pos = match text.find('\n') {
20 None => { 22 None => {
21 return LocalEdit { 23 return LocalEdit {
24 label: "join lines".to_string(),
22 edit: TextEditBuilder::new().finish(), 25 edit: TextEditBuilder::new().finish(),
23 cursor_position: None, 26 cursor_position: None,
24 }; 27 };
@@ -51,6 +54,7 @@ pub fn join_lines(file: &SourceFileNode, range: TextRange) -> LocalEdit {
51 } 54 }
52 55
53 LocalEdit { 56 LocalEdit {
57 label: "join lines".to_string(),
54 edit: edit.finish(), 58 edit: edit.finish(),
55 cursor_position: None, 59 cursor_position: None,
56 } 60 }
@@ -76,6 +80,7 @@ pub fn on_enter(file: &SourceFileNode, offset: TextUnit) -> Option<LocalEdit> {
76 let mut edit = TextEditBuilder::new(); 80 let mut edit = TextEditBuilder::new();
77 edit.insert(offset, inserted); 81 edit.insert(offset, inserted);
78 Some(LocalEdit { 82 Some(LocalEdit {
83 label: "on enter".to_string(),
79 edit: edit.finish(), 84 edit: edit.finish(),
80 cursor_position: Some(cursor_position), 85 cursor_position: Some(cursor_position),
81 }) 86 })
@@ -126,6 +131,7 @@ pub fn on_eq_typed(file: &SourceFileNode, offset: TextUnit) -> Option<LocalEdit>
126 let mut edit = TextEditBuilder::new(); 131 let mut edit = TextEditBuilder::new();
127 edit.insert(offset, ";".to_string()); 132 edit.insert(offset, ";".to_string());
128 Some(LocalEdit { 133 Some(LocalEdit {
134 label: "add semicolon".to_string(),
129 edit: edit.finish(), 135 edit: edit.finish(),
130 cursor_position: None, 136 cursor_position: None,
131 }) 137 })
@@ -249,23 +255,12 @@ fn join_single_use_tree(edit: &mut TextEditBuilder, node: SyntaxNodeRef) -> Opti
249} 255}
250 256
251fn single_use_tree(tree_list: ast::UseTreeList) -> Option<ast::UseTree> { 257fn single_use_tree(tree_list: ast::UseTreeList) -> Option<ast::UseTree> {
252 let mut res = None; 258 let sub_use_trees = tree_list.use_trees().count();
253 for child in tree_list.syntax().children() { 259 if sub_use_trees != 1 {
254 if let Some(tree) = ast::UseTree::cast(child) { 260 return None;
255 if tree.syntax().text().contains('\n') {
256 return None;
257 }
258 if mem::replace(&mut res, Some(tree)).is_some() {
259 return None;
260 }
261 } else {
262 match child.kind() {
263 WHITESPACE | L_CURLY | R_CURLY | COMMA => (),
264 _ => return None,
265 }
266 }
267 } 261 }
268 res 262
263 tree_list.use_trees().next()
269} 264}
270 265
271fn compute_ws(left: SyntaxNodeRef, right: SyntaxNodeRef) -> &'static str { 266fn compute_ws(left: SyntaxNodeRef, right: SyntaxNodeRef) -> &'static str {