From b53a07835b152997a17b2a02dfecba07d5ab5193 Mon Sep 17 00:00:00 2001 From: Ryo Yoshida Date: Fri, 21 Jul 2023 14:26:08 +0900 Subject: [PATCH 1/2] Report incorrect case for fn inner items --- crates/hir-ty/src/diagnostics/decl_check.rs | 44 +++++++++---------- crates/hir/src/lib.rs | 9 +--- .../src/handlers/incorrect_case.rs | 29 ++++++++++++ 3 files changed, 52 insertions(+), 30 deletions(-) diff --git a/crates/hir-ty/src/diagnostics/decl_check.rs b/crates/hir-ty/src/diagnostics/decl_check.rs index 73c8ad3dd5..171f332529 100644 --- a/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/crates/hir-ty/src/diagnostics/decl_check.rs @@ -14,13 +14,12 @@ mod case_conv; use std::fmt; -use base_db::CrateId; use hir_def::{ data::adt::VariantData, hir::{Pat, PatId}, src::HasSource, - AdtId, AttrDefId, ConstId, EnumId, FunctionId, ItemContainerId, Lookup, ModuleDefId, StaticId, - StructId, + AdtId, AttrDefId, ConstId, DefWithBodyId, EnumId, FunctionId, ItemContainerId, Lookup, + ModuleDefId, StaticId, StructId, }; use hir_expand::{ name::{AsName, Name}, @@ -44,13 +43,9 @@ mod allow { pub(super) const NON_CAMEL_CASE_TYPES: &str = "non_camel_case_types"; } -pub fn incorrect_case( - db: &dyn HirDatabase, - krate: CrateId, - owner: ModuleDefId, -) -> Vec { +pub fn incorrect_case(db: &dyn HirDatabase, owner: ModuleDefId) -> Vec { let _p = profile::span("validate_module_item"); - let mut validator = DeclValidator::new(db, krate); + let mut validator = DeclValidator::new(db); validator.validate_item(owner); validator.sink } @@ -120,7 +115,6 @@ pub struct IncorrectCase { pub(super) struct DeclValidator<'a> { db: &'a dyn HirDatabase, - krate: CrateId, pub(super) sink: Vec, } @@ -132,8 +126,8 @@ struct Replacement { } impl<'a> DeclValidator<'a> { - pub(super) fn new(db: &'a dyn HirDatabase, krate: CrateId) -> DeclValidator<'a> { - DeclValidator { db, krate, sink: Vec::new() } + pub(super) fn new(db: &'a dyn HirDatabase) -> DeclValidator<'a> { + DeclValidator { db, sink: Vec::new() } } pub(super) fn validate_item(&mut self, item: ModuleDefId) { @@ -206,17 +200,7 @@ impl<'a> DeclValidator<'a> { return; } - let body = self.db.body(func.into()); - - // Recursively validate inner scope items, such as static variables and constants. - for (_, block_def_map) in body.blocks(self.db.upcast()) { - for (_, module) in block_def_map.modules() { - for def_id in module.scope.declarations() { - let mut validator = DeclValidator::new(self.db, self.krate); - validator.validate_item(def_id); - } - } - } + self.validate_body_inner_items(func.into()); // Check whether non-snake case identifiers are allowed for this function. if self.allowed(func.into(), allow::NON_SNAKE_CASE, false) { @@ -231,6 +215,8 @@ impl<'a> DeclValidator<'a> { expected_case: CaseType::LowerSnakeCase, }); + let body = self.db.body(func.into()); + // Check the patterns inside the function body. // This includes function parameters. let pats_replacements = body @@ -707,4 +693,16 @@ impl<'a> DeclValidator<'a> { self.sink.push(diagnostic); } + + /// Recursively validates inner scope items, such as static variables and constants. + fn validate_body_inner_items(&mut self, body_id: DefWithBodyId) { + let body = self.db.body(body_id); + for (_, block_def_map) in body.blocks(self.db.upcast()) { + for (_, module) in block_def_map.modules() { + for def_id in module.scope.declarations() { + self.validate_item(def_id); + } + } + } + } } diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index f8d9398ae2..fc17568f9e 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -378,11 +378,6 @@ impl ModuleDef { ModuleDef::BuiltinType(_) | ModuleDef::Macro(_) => return Vec::new(), }; - let module = match self.module(db) { - Some(it) => it, - None => return Vec::new(), - }; - let mut acc = Vec::new(); match self.as_def_with_body() { @@ -390,7 +385,7 @@ impl ModuleDef { def.diagnostics(db, &mut acc); } None => { - for diag in hir_ty::diagnostics::incorrect_case(db, module.id.krate(), id) { + for diag in hir_ty::diagnostics::incorrect_case(db, id) { acc.push(diag.into()) } } @@ -1820,7 +1815,7 @@ impl DefWithBody { // FIXME: don't ignore diagnostics for in type const DefWithBody::InTypeConst(_) => return, }; - for diag in hir_ty::diagnostics::incorrect_case(db, krate, def.into()) { + for diag in hir_ty::diagnostics::incorrect_case(db, def.into()) { acc.push(diag.into()) } } diff --git a/crates/ide-diagnostics/src/handlers/incorrect_case.rs b/crates/ide-diagnostics/src/handlers/incorrect_case.rs index 92fd4f71ca..7688230936 100644 --- a/crates/ide-diagnostics/src/handlers/incorrect_case.rs +++ b/crates/ide-diagnostics/src/handlers/incorrect_case.rs @@ -545,4 +545,33 @@ pub static SomeStatic: u8 = 10; "#, ); } + + #[test] + fn fn_inner_items() { + check_diagnostics( + r#" +fn main() { + const foo: bool = true; + //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO` + static bar: bool = true; + //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR` + fn BAZ() { + //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz` + const foo: bool = true; + //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO` + static bar: bool = true; + //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR` + fn BAZ() { + //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz` + let INNER_INNER = 42; + //^^^^^^^^^^^ 💡 warn: Variable `INNER_INNER` should have snake_case name, e.g. `inner_inner` + } + + let INNER_LOCAL = 42; + //^^^^^^^^^^^ 💡 warn: Variable `INNER_LOCAL` should have snake_case name, e.g. `inner_local` + } +} +"#, + ); + } } From 33b7b45f67fbb10fc72611bf489ab014fc5b0932 Mon Sep 17 00:00:00 2001 From: Ryo Yoshida Date: Fri, 21 Jul 2023 15:06:01 +0900 Subject: [PATCH 2/2] Report incorrect case for inner items within all bodies --- crates/hir-ty/src/diagnostics/decl_check.rs | 29 +++++--- .../src/handlers/incorrect_case.rs | 67 +++++++++++++++++++ 2 files changed, 85 insertions(+), 11 deletions(-) diff --git a/crates/hir-ty/src/diagnostics/decl_check.rs b/crates/hir-ty/src/diagnostics/decl_check.rs index 171f332529..5aaa2bcc7c 100644 --- a/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/crates/hir-ty/src/diagnostics/decl_check.rs @@ -18,8 +18,8 @@ use hir_def::{ data::adt::VariantData, hir::{Pat, PatId}, src::HasSource, - AdtId, AttrDefId, ConstId, DefWithBodyId, EnumId, FunctionId, ItemContainerId, Lookup, - ModuleDefId, StaticId, StructId, + AdtId, AttrDefId, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, ItemContainerId, + Lookup, ModuleDefId, StaticId, StructId, }; use hir_expand::{ name::{AsName, Name}, @@ -189,8 +189,7 @@ impl<'a> DeclValidator<'a> { AttrDefId::TypeAliasId(_) => None, AttrDefId::GenericParamId(_) => None, } - .map(|mid| self.allowed(mid, allow_name, true)) - .unwrap_or(false) + .is_some_and(|mid| self.allowed(mid, allow_name, true)) } fn validate_func(&mut self, func: FunctionId) { @@ -482,6 +481,11 @@ impl<'a> DeclValidator<'a> { fn validate_enum(&mut self, enum_id: EnumId) { let data = self.db.enum_data(enum_id); + for (local_id, _) in data.variants.iter() { + let variant_id = EnumVariantId { parent: enum_id, local_id }; + self.validate_body_inner_items(variant_id.into()); + } + // Check whether non-camel case names are allowed for this enum. if self.allowed(enum_id.into(), allow::NON_CAMEL_CASE_TYPES, false) { return; @@ -498,13 +502,11 @@ impl<'a> DeclValidator<'a> { // Check the field names. let enum_fields_replacements = data .variants - .iter() - .filter_map(|(_, variant)| { + .values() + .filter_map(|variant| { Some(Replacement { current_name: variant.name.clone(), - suggested_text: to_camel_case( - &variant.name.display(self.db.upcast()).to_string(), - )?, + suggested_text: to_camel_case(&variant.name.to_smol_str())?, expected_case: CaseType::UpperCamelCase, }) }) @@ -608,6 +610,8 @@ impl<'a> DeclValidator<'a> { fn validate_const(&mut self, const_id: ConstId) { let data = self.db.const_data(const_id); + self.validate_body_inner_items(const_id.into()); + if self.allowed(const_id.into(), allow::NON_UPPER_CASE_GLOBAL, false) { return; } @@ -617,7 +621,7 @@ impl<'a> DeclValidator<'a> { None => return, }; - let const_name = name.display(self.db.upcast()).to_string(); + let const_name = name.to_smol_str(); let replacement = if let Some(new_name) = to_upper_snake_case(&const_name) { Replacement { current_name: name.clone(), @@ -656,13 +660,15 @@ impl<'a> DeclValidator<'a> { return; } + self.validate_body_inner_items(static_id.into()); + if self.allowed(static_id.into(), allow::NON_UPPER_CASE_GLOBAL, false) { return; } let name = &data.name; - let static_name = name.display(self.db.upcast()).to_string(); + let static_name = name.to_smol_str(); let replacement = if let Some(new_name) = to_upper_snake_case(&static_name) { Replacement { current_name: name.clone(), @@ -694,6 +700,7 @@ impl<'a> DeclValidator<'a> { self.sink.push(diagnostic); } + // FIXME: We don't currently validate names within `DefWithBodyId::InTypeConstId`. /// Recursively validates inner scope items, such as static variables and constants. fn validate_body_inner_items(&mut self, body_id: DefWithBodyId) { let body = self.db.body(body_id); diff --git a/crates/ide-diagnostics/src/handlers/incorrect_case.rs b/crates/ide-diagnostics/src/handlers/incorrect_case.rs index 7688230936..235062bf53 100644 --- a/crates/ide-diagnostics/src/handlers/incorrect_case.rs +++ b/crates/ide-diagnostics/src/handlers/incorrect_case.rs @@ -571,6 +571,73 @@ fn main() { //^^^^^^^^^^^ 💡 warn: Variable `INNER_LOCAL` should have snake_case name, e.g. `inner_local` } } +"#, + ); + } + + #[test] + fn const_body_inner_items() { + check_diagnostics( + r#" +const _: () = { + static bar: bool = true; + //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR` + fn BAZ() {} + //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz` + + const foo: () = { + //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO` + const foo: bool = true; + //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO` + static bar: bool = true; + //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR` + fn BAZ() {} + //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz` + }; +}; +"#, + ); + } + + #[test] + fn static_body_inner_items() { + check_diagnostics( + r#" +static FOO: () = { + const foo: bool = true; + //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO` + fn BAZ() {} + //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz` + + static bar: () = { + //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR` + const foo: bool = true; + //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO` + static bar: bool = true; + //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR` + fn BAZ() {} + //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz` + }; +}; +"#, + ); + } + + #[test] + fn enum_variant_body_inner_item() { + check_diagnostics( + r#" +enum E { + A = { + const foo: bool = true; + //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO` + static bar: bool = true; + //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR` + fn BAZ() {} + //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz` + 42 + }, +} "#, ); }