1use hir::{CaseType, InFile, db::ExpandDatabase};
2use ide_db::{assists::Assist, defs::NameClass, rename::RenameDefinition};
3use syntax::AstNode;
4
5use crate::{
6 Diagnostic,
7 DiagnosticCode,
8 DiagnosticsContext,
9 unresolved_fix,
11};
12
13pub(crate) fn incorrect_case(
17 ctx: &DiagnosticsContext<'_, '_>,
18 d: &hir::IncorrectCase,
19) -> Diagnostic {
20 let code = match d.expected_case {
21 CaseType::LowerSnakeCase => DiagnosticCode::RustcLint("non_snake_case"),
22 CaseType::UpperSnakeCase => DiagnosticCode::RustcLint("non_upper_case_globals"),
23 CaseType::UpperCamelCase => DiagnosticCode::RustcLint("non_camel_case_types"),
25 };
26 Diagnostic::new_with_syntax_node_ptr(
27 ctx,
28 code,
29 format!(
30 "{} `{}` should have {} name, e.g. `{}`",
31 d.ident_type, d.ident_text, d.expected_case, d.suggested_text
32 ),
33 InFile::new(d.file, d.ident.into()),
34 )
35 .stable()
36 .with_fixes(fixes(ctx, d))
37}
38
39fn fixes(ctx: &DiagnosticsContext<'_, '_>, d: &hir::IncorrectCase) -> Option<Vec<Assist>> {
40 let root = ctx.sema.db.parse_or_expand(d.file);
41 let name_node = d.ident.to_node(&root);
42 let def = NameClass::classify(&ctx.sema, &name_node)?.defined()?;
43
44 let name_node = InFile::new(d.file, name_node.syntax());
45 let frange = name_node.original_file_range_rooted(ctx.sema.db);
46
47 let label = format!("Rename to {}", d.suggested_text);
48 let mut res = unresolved_fix("change_case", &label, frange.range);
49 if ctx.resolve.should_resolve(&res.id) {
50 let source_change = def.rename(
51 &ctx.sema,
52 &d.suggested_text,
53 RenameDefinition::Yes,
54 &ctx.config.rename_config(),
55 );
56 res.source_change = Some(source_change.ok().unwrap_or_default());
57 }
58
59 Some(vec![res])
60}
61
62#[cfg(test)]
63mod change_case {
64 use crate::tests::{check_diagnostics, check_diagnostics_with_disabled, check_fix};
65
66 #[test]
67 fn test_rename_incorrect_case() {
68 check_fix(
69 r#"
70pub struct test_struct$0 { one: i32 }
71
72pub fn some_fn(val: test_struct) -> test_struct {
73 test_struct { one: val.one + 1 }
74}
75"#,
76 r#"
77pub struct TestStruct { one: i32 }
78
79pub fn some_fn(val: TestStruct) -> TestStruct {
80 TestStruct { one: val.one + 1 }
81}
82"#,
83 );
84
85 check_fix(
86 r#"
87pub fn some_fn(NonSnakeCase$0: u8) -> u8 {
88 NonSnakeCase
89}
90"#,
91 r#"
92pub fn some_fn(non_snake_case: u8) -> u8 {
93 non_snake_case
94}
95"#,
96 );
97
98 check_fix(
99 r#"
100pub fn SomeFn$0(val: u8) -> u8 {
101 if val != 0 { SomeFn(val - 1) } else { val }
102}
103"#,
104 r#"
105pub fn some_fn(val: u8) -> u8 {
106 if val != 0 { some_fn(val - 1) } else { val }
107}
108"#,
109 );
110
111 check_fix(
112 r#"
113fn some_fn() {
114 let whatAWeird_Formatting$0 = 10;
115 another_func(whatAWeird_Formatting);
116}
117"#,
118 r#"
119fn some_fn() {
120 let what_aweird_formatting = 10;
121 another_func(what_aweird_formatting);
122}
123"#,
124 );
125
126 check_fix(
127 r#"
128static S: i32 = M::A;
129
130mod $0M {
131 pub const A: i32 = 10;
132}
133
134mod other {
135 use crate::M::A;
136}
137"#,
138 r#"
139static S: i32 = m::A;
140
141mod m {
142 pub const A: i32 = 10;
143}
144
145mod other {
146 use crate::m::A;
147}
148"#,
149 );
150 }
151
152 #[test]
153 fn test_uppercase_const_no_diagnostics() {
154 check_diagnostics(
155 r#"
156fn foo() {
157 const ANOTHER_ITEM: &str = "some_item";
158}
159"#,
160 );
161 }
162
163 #[test]
164 fn test_rename_incorrect_case_struct_method() {
165 check_fix(
166 r#"
167pub struct TestStruct;
168
169impl TestStruct {
170 pub fn SomeFn$0() -> TestStruct {
171 TestStruct
172 }
173}
174"#,
175 r#"
176pub struct TestStruct;
177
178impl TestStruct {
179 pub fn some_fn() -> TestStruct {
180 TestStruct
181 }
182}
183"#,
184 );
185 }
186
187 #[test]
188 fn test_single_incorrect_case_diagnostic_in_function_name_issue_6970() {
189 check_diagnostics(
190 r#"
191fn FOO() {}
192// ^^^ 💡 warn: Function `FOO` should have snake_case name, e.g. `foo`
193"#,
194 );
195 check_fix(r#"fn FOO$0() {}"#, r#"fn foo() {}"#);
196 }
197
198 #[test]
199 fn incorrect_function_name() {
200 check_diagnostics(
201 r#"
202fn NonSnakeCaseName() {}
203// ^^^^^^^^^^^^^^^^ 💡 warn: Function `NonSnakeCaseName` should have snake_case name, e.g. `non_snake_case_name`
204"#,
205 );
206 }
207
208 #[test]
209 fn incorrect_function_params() {
210 check_diagnostics(
211 r#"
212fn foo(SomeParam: u8) { _ = SomeParam; }
213 // ^^^^^^^^^ 💡 warn: Parameter `SomeParam` should have snake_case name, e.g. `some_param`
214
215fn foo2(ok_param: &str, CAPS_PARAM: u8) { _ = (ok_param, CAPS_PARAM); }
216 // ^^^^^^^^^^ 💡 warn: Parameter `CAPS_PARAM` should have snake_case name, e.g. `caps_param`
217"#,
218 );
219 }
220
221 #[test]
222 fn incorrect_variable_names() {
223 check_diagnostics(
224 r#"
225#[allow(unused)]
226fn foo() {
227 let SOME_VALUE = 10;
228 // ^^^^^^^^^^ 💡 warn: Variable `SOME_VALUE` should have snake_case name, e.g. `some_value`
229 let AnotherValue = 20;
230 // ^^^^^^^^^^^^ 💡 warn: Variable `AnotherValue` should have snake_case name, e.g. `another_value`
231}
232"#,
233 );
234 }
235
236 #[test]
237 fn incorrect_struct_names() {
238 check_diagnostics(
239 r#"
240struct non_camel_case_name {}
241 // ^^^^^^^^^^^^^^^^^^^ 💡 warn: Structure `non_camel_case_name` should have UpperCamelCase name, e.g. `NonCamelCaseName`
242
243struct SCREAMING_CASE {}
244 // ^^^^^^^^^^^^^^ 💡 warn: Structure `SCREAMING_CASE` should have UpperCamelCase name, e.g. `ScreamingCase`
245"#,
246 );
247 }
248
249 #[test]
250 fn no_diagnostic_for_camel_cased_acronyms_in_struct_name() {
251 check_diagnostics(
252 r#"
253struct AABB {}
254"#,
255 );
256 }
257
258 #[test]
259 fn incorrect_struct_field() {
260 check_diagnostics(
261 r#"
262struct SomeStruct { SomeField: u8 }
263 // ^^^^^^^^^ 💡 warn: Field `SomeField` should have snake_case name, e.g. `some_field`
264"#,
265 );
266 }
267
268 #[test]
269 fn incorrect_union_names() {
270 check_diagnostics(
271 r#"
272union non_camel_case_name { field: u8 }
273 // ^^^^^^^^^^^^^^^^^^^ 💡 warn: Union `non_camel_case_name` should have UpperCamelCase name, e.g. `NonCamelCaseName`
274
275union SCREAMING_CASE { field: u8 }
276 // ^^^^^^^^^^^^^^ 💡 warn: Union `SCREAMING_CASE` should have UpperCamelCase name, e.g. `ScreamingCase`
277"#,
278 );
279 }
280
281 #[test]
282 fn no_diagnostic_for_camel_cased_acronyms_in_union_name() {
283 check_diagnostics(
284 r#"
285union AABB { field: u8 }
286"#,
287 );
288 }
289
290 #[test]
291 fn no_diagnostic_for_repr_c_union() {
292 check_diagnostics(
293 r#"
294#[repr(C)]
295union my_union { field: u8 }
296"#,
297 );
298 }
299
300 #[test]
301 fn incorrect_union_field() {
302 check_diagnostics(
303 r#"
304union SomeUnion { SomeField: u8 }
305 // ^^^^^^^^^ 💡 warn: Field `SomeField` should have snake_case name, e.g. `some_field`
306"#,
307 );
308 }
309
310 #[test]
311 fn incorrect_enum_names() {
312 check_diagnostics(
313 r#"
314enum some_enum { Val(u8) }
315 // ^^^^^^^^^ 💡 warn: Enum `some_enum` should have UpperCamelCase name, e.g. `SomeEnum`
316
317enum SOME_ENUM {}
318 // ^^^^^^^^^ 💡 warn: Enum `SOME_ENUM` should have UpperCamelCase name, e.g. `SomeEnum`
319"#,
320 );
321 }
322
323 #[test]
324 fn no_diagnostic_for_camel_cased_acronyms_in_enum_name() {
325 check_diagnostics(
326 r#"
327enum AABB {}
328"#,
329 );
330 }
331
332 #[test]
333 fn incorrect_enum_variant_name() {
334 check_diagnostics(
335 r#"
336enum SomeEnum { SOME_VARIANT(u8) }
337 // ^^^^^^^^^^^^ 💡 warn: Variant `SOME_VARIANT` should have UpperCamelCase name, e.g. `SomeVariant`
338"#,
339 );
340 }
341
342 #[test]
343 fn incorrect_const_name() {
344 check_diagnostics(
345 r#"
346const some_weird_const: u8 = 10;
347 // ^^^^^^^^^^^^^^^^ 💡 warn: Constant `some_weird_const` should have UPPER_SNAKE_CASE name, e.g. `SOME_WEIRD_CONST`
348"#,
349 );
350 }
351
352 #[test]
353 fn incorrect_static_name() {
354 check_diagnostics(
355 r#"
356static some_weird_const: u8 = 10;
357 // ^^^^^^^^^^^^^^^^ 💡 warn: Static variable `some_weird_const` should have UPPER_SNAKE_CASE name, e.g. `SOME_WEIRD_CONST`
358"#,
359 );
360 }
361
362 #[test]
363 fn fn_inside_impl_struct() {
364 check_diagnostics(
365 r#"
366struct someStruct;
367 // ^^^^^^^^^^ 💡 warn: Structure `someStruct` should have UpperCamelCase name, e.g. `SomeStruct`
368
369impl someStruct {
370 fn SomeFunc(&self) {
371 // ^^^^^^^^ 💡 warn: Function `SomeFunc` should have snake_case name, e.g. `some_func`
372 let WHY_VAR_IS_CAPS = 10;
373 // ^^^^^^^^^^^^^^^ 💡 warn: Variable `WHY_VAR_IS_CAPS` should have snake_case name, e.g. `why_var_is_caps`
374 _ = WHY_VAR_IS_CAPS;
375 }
376}
377"#,
378 );
379 }
380
381 #[test]
382 fn no_diagnostic_for_enum_variants() {
383 check_diagnostics(
384 r#"
385enum Option { Some, None }
386use Option::{Some, None};
387
388#[allow(unused)]
389fn main() {
390 match Option::None {
391 None => (),
392 Some => (),
393 }
394}
395"#,
396 );
397 }
398
399 #[test]
400 fn allow_attributes_crate_attr() {
401 check_diagnostics(
402 r#"
403#![allow(non_snake_case)]
404#![allow(non_camel_case_types)]
405
406struct S {
407 fooBar: bool,
408}
409
410enum E {
411 fooBar,
412}
413
414mod F {
415 fn CheckItWorksWithCrateAttr(BAD_NAME_HI: u8) {
416 _ = BAD_NAME_HI;
417 }
418}
419 "#,
420 );
421 }
422
423 #[test]
424 fn external_macro() {
425 check_diagnostics(
426 r#"
427//- /library.rs library crate:library
428#[macro_export]
429macro_rules! trigger_lint {
430 () => { let FOO: () };
431}
432//- /user.rs crate:user deps:library
433fn foo() {
434 library::trigger_lint!();
435}
436 "#,
437 );
438 }
439
440 #[test]
441 fn complex_ignore() {
442 check_diagnostics(
443 r#"
444trait T { fn a(); }
445struct U {}
446impl T for U {
447 fn a() {
448 #[allow(non_snake_case, non_upper_case_globals)]
449 trait __BitFlagsOk {
450 const HiImAlsoBad: u8 = 2;
451 fn Dirty(&self) -> bool { false }
452 }
453
454 trait __BitFlagsBad {
455 const HiImAlsoBad: u8 = 2;
456 // ^^^^^^^^^^^ 💡 warn: Constant `HiImAlsoBad` should have UPPER_SNAKE_CASE name, e.g. `HI_IM_ALSO_BAD`
457 fn Dirty(&self) -> bool { false }
458 // ^^^^^💡 warn: Function `Dirty` should have snake_case name, e.g. `dirty`
459 }
460 }
461}
462"#,
463 );
464 }
465
466 #[test]
467 fn infinite_loop_inner_items() {
468 check_diagnostics(
469 r#"
470fn qualify() {
471 mod foo {
472 use super::*;
473 }
474}
475 "#,
476 )
477 }
478
479 #[test] fn parenthesized_parameter() {
481 check_diagnostics(
482 r#"
483fn f((_O): u8) {}
484 // ^^ 💡 warn: Variable `_O` should have snake_case name, e.g. `_o`
485"#,
486 )
487 }
488
489 #[test]
490 fn ignores_no_mangle_items() {
491 cov_mark::check!(extern_func_no_mangle_ignored);
492 cov_mark::check!(no_mangle_static_incorrect_case_ignored);
493 check_diagnostics(
494 r#"
495#[no_mangle]
496extern "C" fn NonSnakeCaseName(some_var: u8) -> u8;
497#[no_mangle]
498static lower_case: () = ();
499 "#,
500 );
501 }
502
503 #[test]
504 fn ignores_unsafe_no_mangle_items() {
505 cov_mark::check!(extern_func_no_mangle_ignored);
506 cov_mark::check!(no_mangle_static_incorrect_case_ignored);
507 check_diagnostics(
508 r#"
509#[unsafe(no_mangle)]
510extern "C" fn NonSnakeCaseName(some_var: u8) -> u8;
511#[unsafe(no_mangle)]
512static lower_case: () = ();
513 "#,
514 );
515 }
516
517 #[test]
518 fn ignores_no_mangle_items_with_no_abi() {
519 cov_mark::check!(extern_func_no_mangle_ignored);
520 check_diagnostics(
521 r#"
522#[no_mangle]
523extern fn NonSnakeCaseName(some_var: u8) -> u8;
524 "#,
525 );
526 }
527
528 #[test]
529 fn no_mangle_items_with_rust_abi() {
530 check_diagnostics(
531 r#"
532#[no_mangle]
533extern "Rust" fn NonSnakeCaseName(some_var: u8) -> u8;
534 // ^^^^^^^^^^^^^^^^ 💡 warn: Function `NonSnakeCaseName` should have snake_case name, e.g. `non_snake_case_name`
535 "#,
536 );
537 }
538
539 #[test]
540 fn no_mangle_items_non_extern() {
541 check_diagnostics(
542 r#"
543#[no_mangle]
544fn NonSnakeCaseName(some_var: u8) -> u8;
545// ^^^^^^^^^^^^^^^^ 💡 warn: Function `NonSnakeCaseName` should have snake_case name, e.g. `non_snake_case_name`
546 "#,
547 );
548 }
549
550 #[test]
551 fn extern_fn_name() {
552 check_diagnostics(
553 r#"
554extern "C" fn NonSnakeCaseName(some_var: u8) -> u8;
555 // ^^^^^^^^^^^^^^^^ 💡 warn: Function `NonSnakeCaseName` should have snake_case name, e.g. `non_snake_case_name`
556extern "Rust" fn NonSnakeCaseName(some_var: u8) -> u8;
557 // ^^^^^^^^^^^^^^^^ 💡 warn: Function `NonSnakeCaseName` should have snake_case name, e.g. `non_snake_case_name`
558extern fn NonSnakeCaseName(some_var: u8) -> u8;
559 // ^^^^^^^^^^^^^^^^ 💡 warn: Function `NonSnakeCaseName` should have snake_case name, e.g. `non_snake_case_name`
560 "#,
561 );
562 }
563
564 #[test]
565 fn ignores_extern_items() {
566 cov_mark::check!(extern_func_incorrect_case_ignored);
567 cov_mark::check!(extern_static_incorrect_case_ignored);
568 check_diagnostics(
569 r#"
570extern {
571 fn NonSnakeCaseName(SOME_VAR: u8) -> u8;
572 pub static SomeStatic: u8 = 10;
573}
574 "#,
575 );
576 }
577
578 #[test]
579 fn ignores_extern_items_from_macro() {
580 check_diagnostics(
581 r#"
582macro_rules! m {
583 () => {
584 fn NonSnakeCaseName(SOME_VAR: u8) -> u8;
585 pub static SomeStatic: u8 = 10;
586 }
587}
588
589extern {
590 m!();
591}
592 "#,
593 );
594 }
595
596 #[test]
597 fn incorrect_trait_and_assoc_item_names() {
598 check_diagnostics(
599 r#"
600trait BAD_TRAIT {
601 // ^^^^^^^^^ 💡 warn: Trait `BAD_TRAIT` should have UpperCamelCase name, e.g. `BadTrait`
602 const bad_const: u8;
603 // ^^^^^^^^^ 💡 warn: Constant `bad_const` should have UPPER_SNAKE_CASE name, e.g. `BAD_CONST`
604 type BAD_TYPE;
605 // ^^^^^^^^ 💡 warn: Type alias `BAD_TYPE` should have UpperCamelCase name, e.g. `BadType`
606 fn BAD_FUNCTION();
607 // ^^^^^^^^^^^^ 💡 warn: Function `BAD_FUNCTION` should have snake_case name, e.g. `bad_function`
608 fn BadFunction();
609 // ^^^^^^^^^^^ 💡 warn: Function `BadFunction` should have snake_case name, e.g. `bad_function`
610}
611 "#,
612 );
613 }
614
615 #[test]
616 fn no_diagnostics_for_trait_impl_assoc_items_except_pats_in_body() {
617 cov_mark::check!(trait_impl_assoc_const_incorrect_case_ignored);
618 cov_mark::check!(trait_impl_assoc_type_incorrect_case_ignored);
619 cov_mark::check_count!(trait_impl_assoc_func_name_incorrect_case_ignored, 2);
620 check_diagnostics_with_disabled(
621 r#"
622trait BAD_TRAIT {
623 // ^^^^^^^^^ 💡 warn: Trait `BAD_TRAIT` should have UpperCamelCase name, e.g. `BadTrait`
624 const bad_const: u8;
625 // ^^^^^^^^^ 💡 warn: Constant `bad_const` should have UPPER_SNAKE_CASE name, e.g. `BAD_CONST`
626 type BAD_TYPE;
627 // ^^^^^^^^ 💡 warn: Type alias `BAD_TYPE` should have UpperCamelCase name, e.g. `BadType`
628 fn BAD_FUNCTION(BAD_PARAM: u8);
629 // ^^^^^^^^^^^^ 💡 warn: Function `BAD_FUNCTION` should have snake_case name, e.g. `bad_function`
630 // ^^^^^^^^^ 💡 warn: Parameter `BAD_PARAM` should have snake_case name, e.g. `bad_param`
631 fn BadFunction();
632 // ^^^^^^^^^^^ 💡 warn: Function `BadFunction` should have snake_case name, e.g. `bad_function`
633}
634
635impl BAD_TRAIT for () {
636 const bad_const: u8 = 0;
637 type BAD_TYPE = ();
638 fn BAD_FUNCTION(BAD_PARAM: u8) {
639 // ^^^^^^^^^ 💡 warn: Parameter `BAD_PARAM` should have snake_case name, e.g. `bad_param`
640 let BAD_VAR = 0;
641 // ^^^^^^^ 💡 warn: Variable `BAD_VAR` should have snake_case name, e.g. `bad_var`
642 }
643 fn BadFunction() {}
644}
645 "#,
646 &["unused_variables"],
647 );
648 }
649
650 #[test]
651 fn allow_attributes() {
652 check_diagnostics(
653 r#"
654#[allow(non_snake_case)]
655fn NonSnakeCaseName(SOME_VAR: u8) -> u8{
656 // cov_flags generated output from elsewhere in this file
657 extern "C" {
658 #[no_mangle]
659 static lower_case: u8;
660 }
661
662 let OtherVar = SOME_VAR + 1;
663 OtherVar
664}
665
666#[allow(nonstandard_style)]
667mod CheckNonstandardStyle {
668 fn HiImABadFnName() {}
669}
670
671#[allow(bad_style)]
672mod CheckBadStyle {
673 struct fooo;
674}
675
676mod F {
677 #![allow(non_snake_case)]
678 fn CheckItWorksWithModAttr(BAD_NAME_HI: u8) {
679 _ = BAD_NAME_HI;
680 }
681}
682
683#[allow(non_snake_case, non_camel_case_types)]
684pub struct some_type {
685 SOME_FIELD: u8,
686 SomeField: u16,
687}
688
689#[allow(non_upper_case_globals)]
690pub const some_const: u8 = 10;
691
692#[allow(non_upper_case_globals)]
693pub static SomeStatic: u8 = 10;
694
695#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
696trait BAD_TRAIT {
697 const bad_const: u8;
698 type BAD_TYPE;
699 fn BAD_FUNCTION(BAD_PARAM: u8);
700 fn BadFunction();
701}
702 "#,
703 );
704 }
705
706 #[test]
707 fn deny_attributes() {
708 check_diagnostics(
709 r#"
710#[deny(non_snake_case)]
711fn NonSnakeCaseName(some_var: u8) -> u8 {
712 //^^^^^^^^^^^^^^^^ 💡 error: Function `NonSnakeCaseName` should have snake_case name, e.g. `non_snake_case_name`
713 // cov_flags generated output from elsewhere in this file
714 extern "C" {
715 #[no_mangle]
716 static lower_case: u8;
717 }
718
719 let OtherVar = some_var + 1;
720 //^^^^^^^^ 💡 error: Variable `OtherVar` should have snake_case name, e.g. `other_var`
721 OtherVar
722}
723
724#[deny(nonstandard_style)]
725mod CheckNonstandardStyle {
726 //^^^^^^^^^^^^^^^^^^^^^ 💡 error: Module `CheckNonstandardStyle` should have snake_case name, e.g. `check_nonstandard_style`
727 fn HiImABadFnName() {}
728 //^^^^^^^^^^^^^^ 💡 error: Function `HiImABadFnName` should have snake_case name, e.g. `hi_im_abad_fn_name`
729}
730
731#[deny(warnings)]
732mod CheckBadStyle {
733 //^^^^^^^^^^^^^ 💡 error: Module `CheckBadStyle` should have snake_case name, e.g. `check_bad_style`
734 struct fooo;
735 //^^^^ 💡 error: Structure `fooo` should have UpperCamelCase name, e.g. `Fooo`
736}
737
738mod F {
739 //^ 💡 error: Module `F` should have snake_case name, e.g. `f`
740 #![deny(non_snake_case)]
741 fn CheckItWorksWithModAttr() {}
742 //^^^^^^^^^^^^^^^^^^^^^^^ 💡 error: Function `CheckItWorksWithModAttr` should have snake_case name, e.g. `check_it_works_with_mod_attr`
743}
744
745#[deny(non_snake_case, non_camel_case_types)]
746pub struct some_type {
747 //^^^^^^^^^ 💡 error: Structure `some_type` should have UpperCamelCase name, e.g. `SomeType`
748 SOME_FIELD: u8,
749 //^^^^^^^^^^ 💡 error: Field `SOME_FIELD` should have snake_case name, e.g. `some_field`
750 SomeField: u16,
751 //^^^^^^^^^ 💡 error: Field `SomeField` should have snake_case name, e.g. `some_field`
752}
753
754#[deny(non_upper_case_globals)]
755pub const some_const: u8 = 10;
756 //^^^^^^^^^^ 💡 error: Constant `some_const` should have UPPER_SNAKE_CASE name, e.g. `SOME_CONST`
757
758#[deny(non_upper_case_globals)]
759pub static SomeStatic: u8 = 10;
760 //^^^^^^^^^^ 💡 error: Static variable `SomeStatic` should have UPPER_SNAKE_CASE name, e.g. `SOME_STATIC`
761
762#[deny(non_snake_case, non_camel_case_types, non_upper_case_globals)]
763trait BAD_TRAIT {
764 // ^^^^^^^^^ 💡 error: Trait `BAD_TRAIT` should have UpperCamelCase name, e.g. `BadTrait`
765 const bad_const: u8;
766 // ^^^^^^^^^ 💡 error: Constant `bad_const` should have UPPER_SNAKE_CASE name, e.g. `BAD_CONST`
767 type BAD_TYPE;
768 // ^^^^^^^^ 💡 error: Type alias `BAD_TYPE` should have UpperCamelCase name, e.g. `BadType`
769 fn BAD_FUNCTION(BAD_PARAM: u8);
770 // ^^^^^^^^^^^^ 💡 error: Function `BAD_FUNCTION` should have snake_case name, e.g. `bad_function`
771 // ^^^^^^^^^ 💡 error: Parameter `BAD_PARAM` should have snake_case name, e.g. `bad_param`
772 fn BadFunction();
773 // ^^^^^^^^^^^ 💡 error: Function `BadFunction` should have snake_case name, e.g. `bad_function`
774}
775 "#,
776 );
777 }
778
779 #[test]
780 fn fn_inner_items() {
781 check_diagnostics(
782 r#"
783fn main() {
784 const foo: bool = true;
785 //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
786 static bar: bool = true;
787 //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
788 fn BAZ() {
789 //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
790 const foo: bool = true;
791 //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
792 static bar: bool = true;
793 //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
794 fn BAZ() {
795 //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
796 let _INNER_INNER = 42;
797 //^^^^^^^^^^^^ 💡 warn: Variable `_INNER_INNER` should have snake_case name, e.g. `_inner_inner`
798 }
799
800 let _INNER_LOCAL = 42;
801 //^^^^^^^^^^^^ 💡 warn: Variable `_INNER_LOCAL` should have snake_case name, e.g. `_inner_local`
802 }
803}
804"#,
805 );
806 }
807
808 #[test]
809 fn const_body_inner_items() {
810 check_diagnostics(
811 r#"
812const _: () = {
813 static bar: bool = true;
814 //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
815 fn BAZ() {}
816 //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
817
818 const foo: () = {
819 //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
820 const foo: bool = true;
821 //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
822 static bar: bool = true;
823 //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
824 fn BAZ() {}
825 //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
826 };
827};
828"#,
829 );
830 }
831
832 #[test]
833 fn static_body_inner_items() {
834 check_diagnostics(
835 r#"
836static FOO: () = {
837 const foo: bool = true;
838 //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
839 fn BAZ() {}
840 //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
841
842 static bar: () = {
843 //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
844 const foo: bool = true;
845 //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
846 static bar: bool = true;
847 //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
848 fn BAZ() {}
849 //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
850 };
851};
852"#,
853 );
854 }
855
856 #[test]
857 #[should_panic]
859 fn enum_variant_body_inner_item() {
860 check_diagnostics(
861 r#"
862enum E {
863 A = {
864 const foo: bool = true;
865 //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
866 static bar: bool = true;
867 //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
868 fn BAZ() {}
869 //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
870 42
871 },
872}
873"#,
874 );
875 }
876
877 #[test]
878 fn module_name_inline() {
879 check_diagnostics(
880 r#"
881mod M {
882 //^ 💡 warn: Module `M` should have snake_case name, e.g. `m`
883 mod IncorrectCase {}
884 //^^^^^^^^^^^^^ 💡 warn: Module `IncorrectCase` should have snake_case name, e.g. `incorrect_case`
885}
886"#,
887 );
888 }
889
890 #[test]
891 fn module_name_decl() {
892 check_diagnostics(
893 r#"
894//- /Foo.rs
895
896//- /main.rs
897mod Foo;
898 //^^^ 💡 warn: Module `Foo` should have snake_case name, e.g. `foo`
899"#,
900 )
901 }
902
903 #[test]
904 fn test_field_shorthand() {
905 check_diagnostics(
906 r#"
907struct Foo { _nonSnake: u8 }
908 // ^^^^^^^^^ 💡 warn: Field `_nonSnake` should have snake_case name, e.g. `_non_snake`
909fn func(Foo { _nonSnake }: Foo) {}
910"#,
911 );
912 }
913
914 #[test]
915 fn test_match() {
916 check_diagnostics(
917 r#"
918enum Foo { Variant { nonSnake1: u8 } }
919 // ^^^^^^^^^ 💡 warn: Field `nonSnake1` should have snake_case name, e.g. `non_snake1`
920fn func() {
921 match (Foo::Variant { nonSnake1: 1 }) {
922 Foo::Variant { nonSnake1: _nonSnake2 } => {},
923 // ^^^^^^^^^^ 💡 warn: Variable `_nonSnake2` should have snake_case name, e.g. `_non_snake2`
924 }
925}
926"#,
927 );
928
929 check_diagnostics(
930 r#"
931struct Foo(u8);
932
933fn func() {
934 match Foo(1) {
935 Foo(_nonSnake) => {},
936 // ^^^^^^^^^ 💡 warn: Variable `_nonSnake` should have snake_case name, e.g. `_non_snake`
937 }
938}
939"#,
940 );
941
942 check_diagnostics(
943 r#"
944fn main() {
945 match 1 {
946 _Bad1 @ _Bad2 => {}
947 // ^^^^^ 💡 warn: Variable `_Bad1` should have snake_case name, e.g. `_bad1`
948 // ^^^^^ 💡 warn: Variable `_Bad2` should have snake_case name, e.g. `_bad2`
949 }
950}
951"#,
952 );
953 check_diagnostics(
954 r#"
955fn main() {
956 match 1 { _Bad1 => () }
957 // ^^^^^ 💡 warn: Variable `_Bad1` should have snake_case name, e.g. `_bad1`
958}
959"#,
960 );
961
962 check_diagnostics(
963 r#"
964enum Foo { V1, V2 }
965use Foo::V1;
966
967fn main() {
968 match V1 {
969 _Bad1 @ V1 => {},
970 // ^^^^^ 💡 warn: Variable `_Bad1` should have snake_case name, e.g. `_bad1`
971 Foo::V2 => {}
972 }
973}
974"#,
975 );
976 }
977
978 #[test]
979 fn test_for_loop() {
980 check_diagnostics(
981 r#"
982//- minicore: iterators
983fn func() {
984 for _nonSnake in [] {}
985 // ^^^^^^^^^ 💡 warn: Variable `_nonSnake` should have snake_case name, e.g. `_non_snake`
986}
987"#,
988 );
989
990 check_fix(
991 r#"
992//- minicore: iterators
993fn func() {
994 for nonSnake$0 in [] { nonSnake; }
995}
996"#,
997 r#"
998fn func() {
999 for non_snake in [] { non_snake; }
1000}
1001"#,
1002 );
1003 }
1004
1005 #[test]
1006 fn override_lint_level() {
1007 check_diagnostics(
1008 r#"
1009#![allow(unused_variables)]
1010#[warn(nonstandard_style)]
1011fn foo() {
1012 let BAR: i32;
1013 // ^^^ 💡 warn: Variable `BAR` should have snake_case name, e.g. `bar`
1014 #[allow(non_snake_case)]
1015 let FOO: i32;
1016}
1017
1018#[warn(nonstandard_style)]
1019fn foo() {
1020 let BAR: i32;
1021 // ^^^ 💡 warn: Variable `BAR` should have snake_case name, e.g. `bar`
1022 #[expect(non_snake_case)]
1023 let FOO: i32;
1024 #[allow(non_snake_case)]
1025 struct qux;
1026 // ^^^ 💡 warn: Structure `qux` should have UpperCamelCase name, e.g. `Qux`
1027
1028 fn BAZ() {
1029 // ^^^ 💡 error: Function `BAZ` should have snake_case name, e.g. `baz`
1030 #![forbid(bad_style)]
1031 }
1032}
1033 "#,
1034 );
1035 }
1036
1037 #[test]
1038 fn different_files() {
1039 check_diagnostics(
1040 r#"
1041//- /lib.rs
1042#![expect(nonstandard_style)]
1043
1044mod BAD_CASE;
1045
1046fn BAD_CASE() {}
1047
1048//- /BAD_CASE.rs
1049mod OtherBadCase;
1050 // ^^^^^^^^^^^^ 💡 error: Module `OtherBadCase` should have snake_case name, e.g. `other_bad_case`
1051
1052//- /BAD_CASE/OtherBadCase.rs
1053#![allow(non_snake_case)]
1054#![deny(non_snake_case)] // The lint level has been overridden.
1055
1056fn FOO() {}
1057// ^^^ 💡 error: Function `FOO` should have snake_case name, e.g. `foo`
1058
1059#[allow(bad_style)]
1060mod FINE_WITH_BAD_CASE;
1061
1062//- /BAD_CASE/OtherBadCase/FINE_WITH_BAD_CASE.rs
1063struct QUX;
1064const foo: i32 = 0;
1065fn BAR() {
1066 let BAZ: i32;
1067 _ = BAZ;
1068}
1069 "#,
1070 );
1071 }
1072
1073 #[test]
1074 fn cfged_lint_attrs() {
1075 check_diagnostics(
1076 r#"
1077//- /lib.rs cfg:feature=cool_feature
1078#[cfg_attr(any(), allow(non_snake_case))]
1079fn FOO() {}
1080// ^^^ 💡 warn: Function `FOO` should have snake_case name, e.g. `foo`
1081
1082#[cfg_attr(non_existent, allow(non_snake_case))]
1083fn BAR() {}
1084// ^^^ 💡 warn: Function `BAR` should have snake_case name, e.g. `bar`
1085
1086#[cfg_attr(feature = "cool_feature", allow(non_snake_case))]
1087fn BAZ() {}
1088
1089#[cfg_attr(feature = "cool_feature", cfg_attr ( all ( ) , allow ( non_snake_case ) ) ) ]
1090fn QUX() {}
1091 "#,
1092 );
1093 }
1094
1095 #[test]
1096 fn allow_with_comment() {
1097 check_diagnostics(
1098 r#"
1099#[allow(
1100 // Yo, sup
1101 non_snake_case
1102)]
1103fn foo(_HelloWorld: ()) {}
1104 "#,
1105 );
1106 }
1107
1108 #[test]
1109 fn allow_with_repr_c() {
1110 check_diagnostics(
1111 r#"
1112#[repr(C)]
1113struct FFI_Struct;
1114
1115#[repr(C)]
1116enum FFI_Enum {
1117 Field,
1118}
1119 "#,
1120 );
1121 }
1122}