aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_editor/src
diff options
context:
space:
mode:
authorgfreezy <[email protected]>2018-12-25 16:45:13 +0000
committergfreezy <[email protected]>2018-12-25 16:45:13 +0000
commit72eb9de74739887874bebb08c71b574106ae80f1 (patch)
tree9608361dacff1cd3f463c766c0b061f243d38b93 /crates/ra_editor/src
parent5fb426cb9eeefa69a53d7c8c3367f7c6b714b9b8 (diff)
add fix for removing unnecessary braces in use statements
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.rs26
-rw-r--r--crates/ra_editor/src/typing.rs31
3 files changed, 41 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..898d9b8c7 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,27 @@ 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 to_replace = typing::single_use_tree(use_tree_list)
133 .unwrap()
134 .syntax()
135 .text()
136 .to_string();
137 let mut edit_builder = TextEditBuilder::new();
138 edit_builder.delete(range);
139 edit_builder.insert(range.start(), to_replace);
140
128 diagnostics.push(Diagnostic { 141 diagnostics.push(Diagnostic {
129 range: use_tree_list.syntax().range(), 142 range: range,
130 msg: format!("Unnecessary braces in use statement"), 143 msg: format!("Unnecessary braces in use statement"),
131 severity: Severity::WeakWarning, 144 severity: Severity::WeakWarning,
145 fix: Some(LocalEdit {
146 label: "Remove unnecessary braces".to_string(),
147 edit: edit_builder.finish(),
148 cursor_position: None,
149 }),
132 }) 150 })
133 } 151 }
134 } 152 }
@@ -250,9 +268,7 @@ fn main() {}
250 ); 268 );
251 let diagnostics = check_unnecessary_braces_in_use_statement(&file); 269 let diagnostics = check_unnecessary_braces_in_use_statement(&file);
252 assert_eq_dbg( 270 assert_eq_dbg(
253 r#"[Diagnostic { range: [12; 15), msg: "Unnecessary braces in use statement", severity: WeakWarning }, 271 "[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: Some(12) }) }, 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: Some(24) }) }, Diagnostic { range: [61; 64), msg: \"Unnecessary braces in use statement\", severity: WeakWarning, fix: Some(LocalEdit { label: \"Remove unnecessary braces\", edit: TextEdit { atoms: [AtomTextEdit { delete: [61; 61), insert: \"e\" }, AtomTextEdit { delete: [61; 64), insert: \"\" }] }, cursor_position: Some(61) }) }]",
254 Diagnostic { range: [24; 27), msg: "Unnecessary braces in use statement", severity: WeakWarning },
255 Diagnostic { range: [61; 64), msg: "Unnecessary braces in use statement", severity: WeakWarning }]"#,
256 &diagnostics, 272 &diagnostics,
257 ) 273 )
258 } 274 }
diff --git a/crates/ra_editor/src/typing.rs b/crates/ra_editor/src/typing.rs
index 5e412bcfa..dcc8793af 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 })
@@ -248,24 +254,13 @@ fn join_single_use_tree(edit: &mut TextEditBuilder, node: SyntaxNodeRef) -> Opti
248 Some(()) 254 Some(())
249} 255}
250 256
251fn single_use_tree(tree_list: ast::UseTreeList) -> Option<ast::UseTree> { 257pub(crate) fn 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 {