diff options
Diffstat (limited to 'crates/ide_diagnostics/src/handlers/useless_braces.rs')
-rw-r--r-- | crates/ide_diagnostics/src/handlers/useless_braces.rs | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/crates/ide_diagnostics/src/handlers/useless_braces.rs b/crates/ide_diagnostics/src/handlers/useless_braces.rs new file mode 100644 index 000000000..8b9330e04 --- /dev/null +++ b/crates/ide_diagnostics/src/handlers/useless_braces.rs | |||
@@ -0,0 +1,148 @@ | |||
1 | use ide_db::{base_db::FileId, source_change::SourceChange}; | ||
2 | use itertools::Itertools; | ||
3 | use syntax::{ast, AstNode, SyntaxNode, TextRange}; | ||
4 | use text_edit::TextEdit; | ||
5 | |||
6 | use crate::{fix, Diagnostic, Severity}; | ||
7 | |||
8 | // Diagnostic: unnecessary-braces | ||
9 | // | ||
10 | // Diagnostic for unnecessary braces in `use` items. | ||
11 | pub(crate) fn useless_braces( | ||
12 | acc: &mut Vec<Diagnostic>, | ||
13 | file_id: FileId, | ||
14 | node: &SyntaxNode, | ||
15 | ) -> Option<()> { | ||
16 | let use_tree_list = ast::UseTreeList::cast(node.clone())?; | ||
17 | if let Some((single_use_tree,)) = use_tree_list.use_trees().collect_tuple() { | ||
18 | // If there is a comment inside the bracketed `use`, | ||
19 | // assume it is a commented out module path and don't show diagnostic. | ||
20 | if use_tree_list.has_inner_comment() { | ||
21 | return Some(()); | ||
22 | } | ||
23 | |||
24 | let use_range = use_tree_list.syntax().text_range(); | ||
25 | let edit = remove_braces(&single_use_tree).unwrap_or_else(|| { | ||
26 | let to_replace = single_use_tree.syntax().text().to_string(); | ||
27 | let mut edit_builder = TextEdit::builder(); | ||
28 | edit_builder.delete(use_range); | ||
29 | edit_builder.insert(use_range.start(), to_replace); | ||
30 | edit_builder.finish() | ||
31 | }); | ||
32 | |||
33 | acc.push( | ||
34 | Diagnostic::new( | ||
35 | "unnecessary-braces", | ||
36 | "Unnecessary braces in use statement".to_string(), | ||
37 | use_range, | ||
38 | ) | ||
39 | .severity(Severity::WeakWarning) | ||
40 | .with_fixes(Some(vec![fix( | ||
41 | "remove_braces", | ||
42 | "Remove unnecessary braces", | ||
43 | SourceChange::from_text_edit(file_id, edit), | ||
44 | use_range, | ||
45 | )])), | ||
46 | ); | ||
47 | } | ||
48 | |||
49 | Some(()) | ||
50 | } | ||
51 | |||
52 | fn remove_braces(single_use_tree: &ast::UseTree) -> Option<TextEdit> { | ||
53 | let use_tree_list_node = single_use_tree.syntax().parent()?; | ||
54 | if single_use_tree.path()?.segment()?.self_token().is_some() { | ||
55 | let start = use_tree_list_node.prev_sibling_or_token()?.text_range().start(); | ||
56 | let end = use_tree_list_node.text_range().end(); | ||
57 | return Some(TextEdit::delete(TextRange::new(start, end))); | ||
58 | } | ||
59 | None | ||
60 | } | ||
61 | |||
62 | #[cfg(test)] | ||
63 | mod tests { | ||
64 | use crate::tests::{check_diagnostics, check_fix}; | ||
65 | |||
66 | #[test] | ||
67 | fn test_check_unnecessary_braces_in_use_statement() { | ||
68 | check_diagnostics( | ||
69 | r#" | ||
70 | use a; | ||
71 | use a::{c, d::e}; | ||
72 | |||
73 | mod a { | ||
74 | mod c {} | ||
75 | mod d { | ||
76 | mod e {} | ||
77 | } | ||
78 | } | ||
79 | "#, | ||
80 | ); | ||
81 | check_diagnostics( | ||
82 | r#" | ||
83 | use a; | ||
84 | use a::{ | ||
85 | c, | ||
86 | // d::e | ||
87 | }; | ||
88 | |||
89 | mod a { | ||
90 | mod c {} | ||
91 | mod d { | ||
92 | mod e {} | ||
93 | } | ||
94 | } | ||
95 | "#, | ||
96 | ); | ||
97 | check_fix( | ||
98 | r#" | ||
99 | mod b {} | ||
100 | use {$0b}; | ||
101 | "#, | ||
102 | r#" | ||
103 | mod b {} | ||
104 | use b; | ||
105 | "#, | ||
106 | ); | ||
107 | check_fix( | ||
108 | r#" | ||
109 | mod b {} | ||
110 | use {b$0}; | ||
111 | "#, | ||
112 | r#" | ||
113 | mod b {} | ||
114 | use b; | ||
115 | "#, | ||
116 | ); | ||
117 | check_fix( | ||
118 | r#" | ||
119 | mod a { mod c {} } | ||
120 | use a::{c$0}; | ||
121 | "#, | ||
122 | r#" | ||
123 | mod a { mod c {} } | ||
124 | use a::c; | ||
125 | "#, | ||
126 | ); | ||
127 | check_fix( | ||
128 | r#" | ||
129 | mod a {} | ||
130 | use a::{self$0}; | ||
131 | "#, | ||
132 | r#" | ||
133 | mod a {} | ||
134 | use a; | ||
135 | "#, | ||
136 | ); | ||
137 | check_fix( | ||
138 | r#" | ||
139 | mod a { mod c {} mod d { mod e {} } } | ||
140 | use a::{c, d::{e$0}}; | ||
141 | "#, | ||
142 | r#" | ||
143 | mod a { mod c {} mod d { mod e {} } } | ||
144 | use a::{c, d::e}; | ||
145 | "#, | ||
146 | ); | ||
147 | } | ||
148 | } | ||