From 5fe3b75677197964f458f1c7468b383af68f965a Mon Sep 17 00:00:00 2001 From: davidsemakula Date: Thu, 1 Feb 2024 23:22:24 +0300 Subject: [PATCH] incorrect case diagnostics for trait name --- crates/hir-ty/src/diagnostics/decl_check.rs | 50 +++++++++++++++++-- .../src/handlers/incorrect_case.rs | 3 +- 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 78f2005e67..464743135b 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 f5a6aa1197..02f93ca9b8 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(); }