Skip to content

Commit 0ffc088

Browse files
committed
no incorrect case diagnostics for trait impl assoc functions and consts except for pats in fn bodies
1 parent 6d2d632 commit 0ffc088

File tree

2 files changed

+84
-19
lines changed

2 files changed

+84
-19
lines changed

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

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,8 @@ impl<'a> DeclValidator<'a> {
328328
}
329329

330330
fn validate_func(&mut self, func: FunctionId) {
331-
let data = self.db.function_data(func);
332-
if matches!(func.lookup(self.db.upcast()).container, ItemContainerId::ExternBlockId(_)) {
331+
let container = func.lookup(self.db.upcast()).container;
332+
if matches!(container, ItemContainerId::ExternBlockId(_)) {
333333
cov_mark::hit!(extern_func_incorrect_case_ignored);
334334
return;
335335
}
@@ -339,23 +339,48 @@ impl<'a> DeclValidator<'a> {
339339
return;
340340
}
341341

342-
// Check the function name.
343-
let function_name = data.name.display(self.db.upcast()).to_string();
344-
let fn_name_replacement = to_lower_snake_case(&function_name).map(|new_name| Replacement {
345-
current_name: data.name.clone(),
346-
suggested_text: new_name,
347-
expected_case: CaseType::LowerSnakeCase,
348-
});
342+
// Check whether function is an associated item of a trait implementation
343+
let is_trait_impl_assoc_fn = self.is_trait_impl_container(container);
349344

350-
let body = self.db.body(func.into());
345+
// Check the function name.
346+
if !is_trait_impl_assoc_fn {
347+
let data = self.db.function_data(func);
348+
let function_name = data.name.display(self.db.upcast()).to_string();
349+
let fn_name_replacement =
350+
to_lower_snake_case(&function_name).map(|new_name| Replacement {
351+
current_name: data.name.clone(),
352+
suggested_text: new_name,
353+
expected_case: CaseType::LowerSnakeCase,
354+
});
355+
// If there is at least one element to spawn a warning on,
356+
// go to the source map and generate a warning.
357+
if let Some(fn_name_replacement) = fn_name_replacement {
358+
self.create_incorrect_case_diagnostic_for_func(func, fn_name_replacement);
359+
}
360+
} else {
361+
cov_mark::hit!(trait_impl_assoc_func_name_incorrect_case_ignored);
362+
}
351363

352364
// Check the patterns inside the function body.
353-
// This includes function parameters.
365+
// This includes function parameters if it's not an associated function
366+
// of a trait implementation.
367+
let body = self.db.body(func.into());
354368
let pats_replacements = body
355369
.pats
356370
.iter()
357371
.filter_map(|(pat_id, pat)| match pat {
358-
Pat::Bind { id, .. } => Some((pat_id, &body.bindings[*id].name)),
372+
Pat::Bind { id, .. } => {
373+
// Filter out parameters if it's an associated function
374+
// of a trait implementation.
375+
if is_trait_impl_assoc_fn
376+
&& body.params.iter().any(|param_id| *param_id == pat_id)
377+
{
378+
cov_mark::hit!(trait_impl_assoc_func_param_incorrect_case_ignored);
379+
None
380+
} else {
381+
Some((pat_id, &body.bindings[*id].name))
382+
}
383+
}
359384
_ => None,
360385
})
361386
.filter_map(|(id, bind_name)| {
@@ -371,12 +396,6 @@ impl<'a> DeclValidator<'a> {
371396
))
372397
})
373398
.collect();
374-
375-
// If there is at least one element to spawn a warning on, go to the source map and generate a warning.
376-
if let Some(fn_name_replacement) = fn_name_replacement {
377-
self.create_incorrect_case_diagnostic_for_func(func, fn_name_replacement);
378-
}
379-
380399
self.create_incorrect_case_diagnostic_for_variables(func, pats_replacements);
381400
}
382401

@@ -732,6 +751,12 @@ impl<'a> DeclValidator<'a> {
732751
}
733752

734753
fn validate_const(&mut self, const_id: ConstId) {
754+
let container = const_id.lookup(self.db.upcast()).container;
755+
if self.is_trait_impl_container(container) {
756+
cov_mark::hit!(trait_impl_assoc_const_incorrect_case_ignored);
757+
return;
758+
}
759+
735760
let data = self.db.const_data(const_id);
736761

737762
if self.allowed(const_id.into(), allow::NON_UPPER_CASE_GLOBAL, false) {
@@ -819,4 +844,13 @@ impl<'a> DeclValidator<'a> {
819844

820845
self.sink.push(diagnostic);
821846
}
847+
848+
fn is_trait_impl_container(&self, container_id: ItemContainerId) -> bool {
849+
if let ItemContainerId::ImplId(impl_id) = container_id {
850+
if self.db.impl_trait(impl_id).is_some() {
851+
return true;
852+
}
853+
}
854+
false
855+
}
822856
}

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

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::IncorrectCase) -> Option<Vec<Ass
5252

5353
#[cfg(test)]
5454
mod change_case {
55-
use crate::tests::{check_diagnostics, check_fix};
55+
use crate::tests::{check_diagnostics, check_diagnostics_with_disabled, check_fix};
5656

5757
#[test]
5858
fn test_rename_incorrect_case() {
@@ -479,6 +479,37 @@ trait BAD_TRAIT {
479479
);
480480
}
481481

482+
#[test]
483+
fn no_diagnostics_for_trait_impl_assoc_items_except_pats_in_body() {
484+
cov_mark::check!(trait_impl_assoc_const_incorrect_case_ignored);
485+
cov_mark::check_count!(trait_impl_assoc_func_name_incorrect_case_ignored, 2);
486+
cov_mark::check!(trait_impl_assoc_func_param_incorrect_case_ignored);
487+
check_diagnostics_with_disabled(
488+
r#"
489+
trait BAD_TRAIT {
490+
// ^^^^^^^^^ 💡 warn: Trait `BAD_TRAIT` should have CamelCase name, e.g. `BadTrait`
491+
const bad_const: u8;
492+
// ^^^^^^^^^ 💡 warn: Constant `bad_const` should have UPPER_SNAKE_CASE name, e.g. `BAD_CONST`
493+
fn BAD_FUNCTION(BAD_PARAM: u8);
494+
// ^^^^^^^^^^^^ 💡 warn: Function `BAD_FUNCTION` should have snake_case name, e.g. `bad_function`
495+
// ^^^^^^^^^ 💡 warn: Parameter `BAD_PARAM` should have snake_case name, e.g. `bad_param`
496+
fn BadFunction();
497+
// ^^^^^^^^^^^ 💡 warn: Function `BadFunction` should have snake_case name, e.g. `bad_function`
498+
}
499+
500+
impl BAD_TRAIT for () {
501+
const bad_const: u8 = 1;
502+
fn BAD_FUNCTION(BAD_PARAM: u8) {
503+
let BAD_VAR = 10;
504+
// ^^^^^^^ 💡 warn: Variable `BAD_VAR` should have snake_case name, e.g. `bad_var`
505+
}
506+
fn BadFunction() {}
507+
}
508+
"#,
509+
std::iter::once("unused_variables".to_string()),
510+
);
511+
}
512+
482513
#[test]
483514
fn allow_attributes() {
484515
check_diagnostics(

0 commit comments

Comments
 (0)