Skip to content

Commit 080d223

Browse files
committed
incorrect case diagnostics for type aliases
1 parent 0ffc088 commit 080d223

File tree

3 files changed

+76
-15
lines changed

3 files changed

+76
-15
lines changed

crates/hir-ty/src/diagnostics/decl_check.rs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use hir_def::{
2020
hir::{Pat, PatId},
2121
src::HasSource,
2222
AdtId, AttrDefId, ConstId, EnumId, FunctionId, ItemContainerId, Lookup, ModuleDefId, ModuleId,
23-
StaticId, StructId, TraitId,
23+
StaticId, StructId, TraitId, TypeAliasId,
2424
};
2525
use hir_expand::{
2626
name::{AsName, Name},
@@ -84,6 +84,7 @@ pub enum IdentType {
8484
StaticVariable,
8585
Structure,
8686
Trait,
87+
TypeAlias,
8788
Variable,
8889
Variant,
8990
}
@@ -100,6 +101,7 @@ impl fmt::Display for IdentType {
100101
IdentType::StaticVariable => "Static variable",
101102
IdentType::Structure => "Structure",
102103
IdentType::Trait => "Trait",
104+
IdentType::TypeAlias => "Type alias",
103105
IdentType::Variable => "Variable",
104106
IdentType::Variant => "Variant",
105107
};
@@ -143,6 +145,7 @@ impl<'a> DeclValidator<'a> {
143145
ModuleDefId::AdtId(adt) => self.validate_adt(adt),
144146
ModuleDefId::ConstId(const_id) => self.validate_const(const_id),
145147
ModuleDefId::StaticId(static_id) => self.validate_static(static_id),
148+
ModuleDefId::TypeAliasId(type_alias_id) => self.validate_type_alias(type_alias_id),
146149
_ => (),
147150
}
148151
}
@@ -845,6 +848,54 @@ impl<'a> DeclValidator<'a> {
845848
self.sink.push(diagnostic);
846849
}
847850

851+
fn validate_type_alias(&mut self, type_alias_id: TypeAliasId) {
852+
let container = type_alias_id.lookup(self.db.upcast()).container;
853+
if self.is_trait_impl_container(container) {
854+
cov_mark::hit!(trait_impl_assoc_type_incorrect_case_ignored);
855+
return;
856+
}
857+
858+
// Check whether non-snake case identifiers are allowed for this type alias.
859+
if self.allowed(type_alias_id.into(), allow::NON_CAMEL_CASE_TYPES, false) {
860+
return;
861+
}
862+
863+
// Check the type alias name.
864+
let data = self.db.type_alias_data(type_alias_id);
865+
let type_alias_name = data.name.display(self.db.upcast()).to_string();
866+
let type_alias_name_replacement =
867+
to_camel_case(&type_alias_name).map(|new_name| Replacement {
868+
current_name: data.name.clone(),
869+
suggested_text: new_name,
870+
expected_case: CaseType::UpperCamelCase,
871+
});
872+
873+
if let Some(replacement) = type_alias_name_replacement {
874+
let type_alias_loc = type_alias_id.lookup(self.db.upcast());
875+
let type_alias_src = type_alias_loc.source(self.db.upcast());
876+
877+
let Some(ast_ptr) = type_alias_src.value.name() else {
878+
never!(
879+
"Replacement ({:?}) was generated for a type alias without a name: {:?}",
880+
replacement,
881+
type_alias_src
882+
);
883+
return;
884+
};
885+
886+
let diagnostic = IncorrectCase {
887+
file: type_alias_src.file_id,
888+
ident_type: IdentType::TypeAlias,
889+
ident: AstPtr::new(&ast_ptr),
890+
expected_case: replacement.expected_case,
891+
ident_text: type_alias_name,
892+
suggested_text: replacement.suggested_text,
893+
};
894+
895+
self.sink.push(diagnostic);
896+
}
897+
}
898+
848899
fn is_trait_impl_container(&self, container_id: ItemContainerId) -> bool {
849900
if let ItemContainerId::ImplId(impl_id) = container_id {
850901
if self.db.impl_trait(impl_id).is_some() {

crates/hir/src/lib.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -565,13 +565,7 @@ impl Module {
565565
}
566566

567567
for item in t.items(db) {
568-
let def: DefWithBody = match item {
569-
AssocItem::Function(it) => it.into(),
570-
AssocItem::Const(it) => it.into(),
571-
AssocItem::TypeAlias(_) => continue,
572-
};
573-
574-
def.diagnostics(db, acc);
568+
item.diagnostics(db, acc);
575569
}
576570

577571
acc.extend(def.diagnostics(db))
@@ -741,13 +735,7 @@ impl Module {
741735
}
742736

743737
for &item in &db.impl_data(impl_def.id).items {
744-
let def: DefWithBody = match AssocItem::from(item) {
745-
AssocItem::Function(it) => it.into(),
746-
AssocItem::Const(it) => it.into(),
747-
AssocItem::TypeAlias(_) => continue,
748-
};
749-
750-
def.diagnostics(db, acc);
738+
AssocItem::from(item).diagnostics(db, acc);
751739
}
752740
}
753741
}
@@ -2662,6 +2650,22 @@ impl AssocItem {
26622650
_ => None,
26632651
}
26642652
}
2653+
2654+
pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
2655+
match self {
2656+
AssocItem::Function(func) => {
2657+
DefWithBody::from(func).diagnostics(db, acc);
2658+
}
2659+
AssocItem::Const(const_) => {
2660+
DefWithBody::from(const_).diagnostics(db, acc);
2661+
}
2662+
AssocItem::TypeAlias(type_alias) => {
2663+
for diag in hir_ty::diagnostics::incorrect_case(db, type_alias.id.into()) {
2664+
acc.push(diag.into());
2665+
}
2666+
}
2667+
}
2668+
}
26652669
}
26662670

26672671
impl HasVisibility for AssocItem {

crates/ide-diagnostics/src/handlers/incorrect_case.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,8 @@ trait BAD_TRAIT {
470470
// ^^^^^^^^^ 💡 warn: Trait `BAD_TRAIT` should have CamelCase name, e.g. `BadTrait`
471471
const bad_const: u8;
472472
// ^^^^^^^^^ 💡 warn: Constant `bad_const` should have UPPER_SNAKE_CASE name, e.g. `BAD_CONST`
473+
type BAD_TYPE;
474+
// ^^^^^^^^ 💡 warn: Type alias `BAD_TYPE` should have CamelCase name, e.g. `BadType`
473475
fn BAD_FUNCTION();
474476
// ^^^^^^^^^^^^ 💡 warn: Function `BAD_FUNCTION` should have snake_case name, e.g. `bad_function`
475477
fn BadFunction();
@@ -482,6 +484,7 @@ trait BAD_TRAIT {
482484
#[test]
483485
fn no_diagnostics_for_trait_impl_assoc_items_except_pats_in_body() {
484486
cov_mark::check!(trait_impl_assoc_const_incorrect_case_ignored);
487+
cov_mark::check!(trait_impl_assoc_type_incorrect_case_ignored);
485488
cov_mark::check_count!(trait_impl_assoc_func_name_incorrect_case_ignored, 2);
486489
cov_mark::check!(trait_impl_assoc_func_param_incorrect_case_ignored);
487490
check_diagnostics_with_disabled(
@@ -490,6 +493,8 @@ trait BAD_TRAIT {
490493
// ^^^^^^^^^ 💡 warn: Trait `BAD_TRAIT` should have CamelCase name, e.g. `BadTrait`
491494
const bad_const: u8;
492495
// ^^^^^^^^^ 💡 warn: Constant `bad_const` should have UPPER_SNAKE_CASE name, e.g. `BAD_CONST`
496+
type BAD_TYPE;
497+
// ^^^^^^^^ 💡 warn: Type alias `BAD_TYPE` should have CamelCase name, e.g. `BadType`
493498
fn BAD_FUNCTION(BAD_PARAM: u8);
494499
// ^^^^^^^^^^^^ 💡 warn: Function `BAD_FUNCTION` should have snake_case name, e.g. `bad_function`
495500
// ^^^^^^^^^ 💡 warn: Parameter `BAD_PARAM` should have snake_case name, e.g. `bad_param`
@@ -499,6 +504,7 @@ trait BAD_TRAIT {
499504
500505
impl BAD_TRAIT for () {
501506
const bad_const: u8 = 1;
507+
type BAD_TYPE = ();
502508
fn BAD_FUNCTION(BAD_PARAM: u8) {
503509
let BAD_VAR = 10;
504510
// ^^^^^^^ 💡 warn: Variable `BAD_VAR` should have snake_case name, e.g. `bad_var`

0 commit comments

Comments
 (0)