aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_diagnostics/src/handlers/useless_braces.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_diagnostics/src/handlers/useless_braces.rs')
-rw-r--r--crates/ide_diagnostics/src/handlers/useless_braces.rs148
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 @@
1use ide_db::{base_db::FileId, source_change::SourceChange};
2use itertools::Itertools;
3use syntax::{ast, AstNode, SyntaxNode, TextRange};
4use text_edit::TextEdit;
5
6use crate::{fix, Diagnostic, Severity};
7
8// Diagnostic: unnecessary-braces
9//
10// Diagnostic for unnecessary braces in `use` items.
11pub(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
52fn 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)]
63mod 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#"
70use a;
71use a::{c, d::e};
72
73mod a {
74 mod c {}
75 mod d {
76 mod e {}
77 }
78}
79"#,
80 );
81 check_diagnostics(
82 r#"
83use a;
84use a::{
85 c,
86 // d::e
87};
88
89mod a {
90 mod c {}
91 mod d {
92 mod e {}
93 }
94}
95"#,
96 );
97 check_fix(
98 r#"
99mod b {}
100use {$0b};
101"#,
102 r#"
103mod b {}
104use b;
105"#,
106 );
107 check_fix(
108 r#"
109mod b {}
110use {b$0};
111"#,
112 r#"
113mod b {}
114use b;
115"#,
116 );
117 check_fix(
118 r#"
119mod a { mod c {} }
120use a::{c$0};
121"#,
122 r#"
123mod a { mod c {} }
124use a::c;
125"#,
126 );
127 check_fix(
128 r#"
129mod a {}
130use a::{self$0};
131"#,
132 r#"
133mod a {}
134use a;
135"#,
136 );
137 check_fix(
138 r#"
139mod a { mod c {} mod d { mod e {} } }
140use a::{c, d::{e$0}};
141"#,
142 r#"
143mod a { mod c {} mod d { mod e {} } }
144use a::{c, d::e};
145"#,
146 );
147 }
148}