aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/diagnostics/incorrect_case.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2021-06-13 19:09:03 +0100
committerAleksey Kladov <[email protected]>2021-06-13 19:09:03 +0100
commitfc30c5ccbeba2a102922da497809dd3f812544c4 (patch)
treeed3067580e998f04e94bfb93508fe3f12c851c3b /crates/ide/src/diagnostics/incorrect_case.rs
parent2ad78924621420cb323efdeb3d875ca3f47d940f (diff)
internal: refactor incorrect case diagnostics
Diffstat (limited to 'crates/ide/src/diagnostics/incorrect_case.rs')
-rw-r--r--crates/ide/src/diagnostics/incorrect_case.rs166
1 files changed, 166 insertions, 0 deletions
diff --git a/crates/ide/src/diagnostics/incorrect_case.rs b/crates/ide/src/diagnostics/incorrect_case.rs
new file mode 100644
index 000000000..56283b58b
--- /dev/null
+++ b/crates/ide/src/diagnostics/incorrect_case.rs
@@ -0,0 +1,166 @@
1use hir::{db::AstDatabase, InFile};
2use ide_assists::Assist;
3use ide_db::base_db::FilePosition;
4use syntax::AstNode;
5
6use crate::{
7 diagnostics::{unresolved_fix, Diagnostic, DiagnosticsContext},
8 references::rename::rename_with_semantics,
9 Severity,
10};
11
12// Diagnostic: incorrect-ident-case
13//
14// This diagnostic is triggered if an item name doesn't follow https://doc.rust-lang.org/1.0.0/style/style/naming/README.html[Rust naming convention].
15pub(super) fn incorrect_case(ctx: &DiagnosticsContext<'_>, d: &hir::IncorrectCase) -> Diagnostic {
16 Diagnostic::new(
17 "incorrect-ident-case",
18 format!(
19 "{} `{}` should have {} name, e.g. `{}`",
20 d.ident_type, d.ident_text, d.expected_case, d.suggested_text
21 ),
22 ctx.sema.diagnostics_display_range(InFile::new(d.file, d.ident.clone().into())).range,
23 )
24 .severity(Severity::WeakWarning)
25 .with_fixes(fixes(ctx, d))
26}
27
28fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::IncorrectCase) -> Option<Vec<Assist>> {
29 let root = ctx.sema.db.parse_or_expand(d.file)?;
30 let name_node = d.ident.to_node(&root);
31
32 let name_node = InFile::new(d.file, name_node.syntax());
33 let frange = name_node.original_file_range(ctx.sema.db);
34 let file_position = FilePosition { file_id: frange.file_id, offset: frange.range.start() };
35
36 let label = format!("Rename to {}", d.suggested_text);
37 let mut res = unresolved_fix("change_case", &label, frange.range);
38 if ctx.resolve.should_resolve(&res.id) {
39 let source_change = rename_with_semantics(&ctx.sema, file_position, &d.suggested_text);
40 res.source_change = Some(source_change.ok().unwrap_or_default());
41 }
42
43 Some(vec![res])
44}
45
46#[cfg(test)]
47mod change_case {
48 use crate::{
49 diagnostics::tests::{check_diagnostics, check_fix},
50 fixture, AssistResolveStrategy, DiagnosticsConfig,
51 };
52
53 #[test]
54 fn test_rename_incorrect_case() {
55 check_fix(
56 r#"
57pub struct test_struct$0 { one: i32 }
58
59pub fn some_fn(val: test_struct) -> test_struct {
60 test_struct { one: val.one + 1 }
61}
62"#,
63 r#"
64pub struct TestStruct { one: i32 }
65
66pub fn some_fn(val: TestStruct) -> TestStruct {
67 TestStruct { one: val.one + 1 }
68}
69"#,
70 );
71
72 check_fix(
73 r#"
74pub fn some_fn(NonSnakeCase$0: u8) -> u8 {
75 NonSnakeCase
76}
77"#,
78 r#"
79pub fn some_fn(non_snake_case: u8) -> u8 {
80 non_snake_case
81}
82"#,
83 );
84
85 check_fix(
86 r#"
87pub fn SomeFn$0(val: u8) -> u8 {
88 if val != 0 { SomeFn(val - 1) } else { val }
89}
90"#,
91 r#"
92pub fn some_fn(val: u8) -> u8 {
93 if val != 0 { some_fn(val - 1) } else { val }
94}
95"#,
96 );
97
98 check_fix(
99 r#"
100fn some_fn() {
101 let whatAWeird_Formatting$0 = 10;
102 another_func(whatAWeird_Formatting);
103}
104"#,
105 r#"
106fn some_fn() {
107 let what_a_weird_formatting = 10;
108 another_func(what_a_weird_formatting);
109}
110"#,
111 );
112 }
113
114 #[test]
115 fn test_uppercase_const_no_diagnostics() {
116 check_diagnostics(
117 r#"
118fn foo() {
119 const ANOTHER_ITEM$0: &str = "some_item";
120}
121"#,
122 );
123 }
124
125 #[test]
126 fn test_rename_incorrect_case_struct_method() {
127 check_fix(
128 r#"
129pub struct TestStruct;
130
131impl TestStruct {
132 pub fn SomeFn$0() -> TestStruct {
133 TestStruct
134 }
135}
136"#,
137 r#"
138pub struct TestStruct;
139
140impl TestStruct {
141 pub fn some_fn() -> TestStruct {
142 TestStruct
143 }
144}
145"#,
146 );
147 }
148
149 #[test]
150 fn test_single_incorrect_case_diagnostic_in_function_name_issue_6970() {
151 let input = r#"fn FOO$0() {}"#;
152 let expected = r#"fn foo() {}"#;
153
154 let (analysis, file_position) = fixture::position(input);
155 let diagnostics = analysis
156 .diagnostics(
157 &DiagnosticsConfig::default(),
158 AssistResolveStrategy::All,
159 file_position.file_id,
160 )
161 .unwrap();
162 assert_eq!(diagnostics.len(), 1);
163
164 check_fix(input, expected);
165 }
166}