about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir-ty/src/diagnostics/decl_check.rs50
-rw-r--r--crates/ide-diagnostics/src/handlers/incorrect_case.rs3
2 files changed, 49 insertions, 4 deletions
diff --git a/crates/hir-ty/src/diagnostics/decl_check.rs b/crates/hir-ty/src/diagnostics/decl_check.rs
index 78f2005e676..464743135be 100644
--- a/crates/hir-ty/src/diagnostics/decl_check.rs
+++ b/crates/hir-ty/src/diagnostics/decl_check.rs
@@ -20,7 +20,7 @@ use hir_def::{
     hir::{Pat, PatId},
     src::HasSource,
     AdtId, AttrDefId, ConstId, EnumId, FunctionId, ItemContainerId, Lookup, ModuleDefId, ModuleId,
-    StaticId, StructId,
+    StaticId, StructId, TraitId,
 };
 use hir_expand::{
     name::{AsName, Name},
@@ -79,12 +79,13 @@ pub enum IdentType {
     Enum,
     Field,
     Function,
+    Module,
     Parameter,
     StaticVariable,
     Structure,
+    Trait,
     Variable,
     Variant,
-    Module,
 }
 
 impl fmt::Display for IdentType {
@@ -94,12 +95,13 @@ impl fmt::Display for IdentType {
             IdentType::Enum => "Enum",
             IdentType::Field => "Field",
             IdentType::Function => "Function",
+            IdentType::Module => "Module",
             IdentType::Parameter => "Parameter",
             IdentType::StaticVariable => "Static variable",
             IdentType::Structure => "Structure",
+            IdentType::Trait => "Trait",
             IdentType::Variable => "Variable",
             IdentType::Variant => "Variant",
-            IdentType::Module => "Module",
         };
 
         repr.fmt(f)
@@ -136,6 +138,7 @@ impl<'a> DeclValidator<'a> {
     pub(super) fn validate_item(&mut self, item: ModuleDefId) {
         match item {
             ModuleDefId::ModuleId(module_id) => self.validate_module(module_id),
+            ModuleDefId::TraitId(trait_id) => self.validate_trait(trait_id),
             ModuleDefId::FunctionId(func) => self.validate_func(func),
             ModuleDefId::AdtId(adt) => self.validate_adt(adt),
             ModuleDefId::ConstId(const_id) => self.validate_const(const_id),
@@ -283,6 +286,47 @@ impl<'a> DeclValidator<'a> {
         }
     }
 
+    fn validate_trait(&mut self, trait_id: TraitId) {
+        // Check whether non-snake case identifiers are allowed for this trait.
+        if self.allowed(trait_id.into(), allow::NON_CAMEL_CASE_TYPES, false) {
+            return;
+        }
+
+        // Check the trait name.
+        let data = self.db.trait_data(trait_id);
+        let trait_name = data.name.display(self.db.upcast()).to_string();
+        let trait_name_replacement = to_camel_case(&trait_name).map(|new_name| Replacement {
+            current_name: data.name.clone(),
+            suggested_text: new_name,
+            expected_case: CaseType::UpperCamelCase,
+        });
+
+        if let Some(replacement) = trait_name_replacement {
+            let trait_loc = trait_id.lookup(self.db.upcast());
+            let trait_src = trait_loc.source(self.db.upcast());
+
+            let Some(ast_ptr) = trait_src.value.name() else {
+                never!(
+                    "Replacement ({:?}) was generated for a trait without a name: {:?}",
+                    replacement,
+                    trait_src
+                );
+                return;
+            };
+
+            let diagnostic = IncorrectCase {
+                file: trait_src.file_id,
+                ident_type: IdentType::Trait,
+                ident: AstPtr::new(&ast_ptr),
+                expected_case: replacement.expected_case,
+                ident_text: trait_name,
+                suggested_text: replacement.suggested_text,
+            };
+
+            self.sink.push(diagnostic);
+        }
+    }
+
     fn validate_func(&mut self, func: FunctionId) {
         let data = self.db.function_data(func);
         if matches!(func.lookup(self.db.upcast()).container, ItemContainerId::ExternBlockId(_)) {
diff --git a/crates/ide-diagnostics/src/handlers/incorrect_case.rs b/crates/ide-diagnostics/src/handlers/incorrect_case.rs
index f5a6aa11979..02f93ca9b85 100644
--- a/crates/ide-diagnostics/src/handlers/incorrect_case.rs
+++ b/crates/ide-diagnostics/src/handlers/incorrect_case.rs
@@ -462,12 +462,13 @@ extern {
     }
 
     #[test]
-    fn bug_traits_arent_checked() {
+    fn incorrect_trait_and_assoc_item_names() {
         // FIXME: Traits and functions in traits aren't currently checked by
         // r-a, even though rustc will complain about them.
         check_diagnostics(
             r#"
 trait BAD_TRAIT {
+   // ^^^^^^^^^ 💡 warn: Trait `BAD_TRAIT` should have CamelCase name, e.g. `BadTrait`
     fn BAD_FUNCTION();
     fn BadFunction();
 }