@@ -16,12 +16,9 @@ mod case_conv;
1616use std:: fmt;
1717
1818use hir_def:: {
19- data:: adt:: VariantData ,
20- db:: DefDatabase ,
21- hir:: { Pat , PatId } ,
22- src:: HasSource ,
23- AdtId , AttrDefId , ConstId , EnumId , FunctionId , ItemContainerId , Lookup , ModuleDefId , ModuleId ,
24- StaticId , StructId , TraitId , TypeAliasId ,
19+ data:: adt:: VariantData , db:: DefDatabase , hir:: Pat , src:: HasSource , AdtId , AttrDefId , ConstId ,
20+ EnumId , FunctionId , ItemContainerId , Lookup , ModuleDefId , ModuleId , StaticId , StructId ,
21+ TraitId , TypeAliasId ,
2522} ;
2623use hir_expand:: {
2724 name:: { AsName , Name } ,
@@ -298,11 +295,9 @@ impl<'a> DeclValidator<'a> {
298295 return ;
299296 }
300297
301- // Check whether function is an associated item of a trait implementation
302- let is_trait_impl_assoc_fn = self . is_trait_impl_container ( container) ;
303-
304298 // Check the function name.
305- if !is_trait_impl_assoc_fn {
299+ // Skipped if function is an associated item of a trait implementation.
300+ if !self . is_trait_impl_container ( container) {
306301 let data = self . db . function_data ( func) ;
307302 self . create_incorrect_case_diagnostic_for_item_name (
308303 func,
@@ -315,91 +310,80 @@ impl<'a> DeclValidator<'a> {
315310 }
316311
317312 // Check the patterns inside the function body.
318- // This includes function parameters if it's not an associated function
319- // of a trait implementation.
313+ self . validate_func_body ( func) ;
314+ }
315+
316+ /// Check incorrect names for patterns inside the function body.
317+ /// This includes function parameters except for trait implementation associated functions.
318+ fn validate_func_body ( & mut self , func : FunctionId ) {
319+ // Check whether function is an associated item of a trait implementation
320+ let container = func. lookup ( self . db . upcast ( ) ) . container ;
321+ let is_trait_impl_assoc_fn = self . is_trait_impl_container ( container) ;
322+
320323 let body = self . db . body ( func. into ( ) ) ;
321- let pats_replacements = body
324+ let mut pats_replacements = body
322325 . pats
323326 . iter ( )
324327 . filter_map ( |( pat_id, pat) | match pat {
325328 Pat :: Bind { id, .. } => {
326- // Filter out parameters if it's an associated function
327- // of a trait implementation.
329+ // Filter out parameters for trait implementation associated functions.
328330 if is_trait_impl_assoc_fn
329331 && body. params . iter ( ) . any ( |param_id| * param_id == pat_id)
330332 {
331333 cov_mark:: hit!( trait_impl_assoc_func_param_incorrect_case_ignored) ;
332334 None
333335 } else {
334- Some ( ( pat_id, & body. bindings [ * id] . name ) )
336+ let bind_name = & body. bindings [ * id] . name ;
337+ let replacement = Replacement {
338+ current_name : bind_name. clone ( ) ,
339+ suggested_text : to_lower_snake_case ( & bind_name. to_smol_str ( ) ) ?,
340+ expected_case : CaseType :: LowerSnakeCase ,
341+ } ;
342+ Some ( ( pat_id, replacement) )
335343 }
336344 }
337345 _ => None ,
338346 } )
339- . filter_map ( |( id, bind_name) | {
340- Some ( (
341- id,
342- Replacement {
343- current_name : bind_name. clone ( ) ,
344- suggested_text : to_lower_snake_case (
345- & bind_name. display ( self . db . upcast ( ) ) . to_string ( ) ,
346- ) ?,
347- expected_case : CaseType :: LowerSnakeCase ,
348- } ,
349- ) )
350- } )
351- . collect ( ) ;
352- self . create_incorrect_case_diagnostic_for_func_variables ( func, pats_replacements) ;
353- }
347+ . peekable ( ) ;
354348
355- /// Given the information about incorrect variable names, looks up into the source code
356- /// for exact locations and adds diagnostics into the sink.
357- fn create_incorrect_case_diagnostic_for_func_variables (
358- & mut self ,
359- func : FunctionId ,
360- pats_replacements : Vec < ( PatId , Replacement ) > ,
361- ) {
362349 // XXX: only look at source_map if we do have missing fields
363- if pats_replacements. is_empty ( ) {
350+ if pats_replacements. peek ( ) . is_none ( ) {
364351 return ;
365352 }
366353
367354 let ( _, source_map) = self . db . body_with_source_map ( func. into ( ) ) ;
368-
369355 for ( id, replacement) in pats_replacements {
370- if let Ok ( source_ptr) = source_map. pat_syntax ( id) {
371- if let Some ( ptr) = source_ptr. value . cast :: < ast:: IdentPat > ( ) {
372- let root = source_ptr. file_syntax ( self . db . upcast ( ) ) ;
373- let ident_pat = ptr. to_node ( & root) ;
374- let parent = match ident_pat. syntax ( ) . parent ( ) {
375- Some ( parent) => parent,
376- None => continue ,
377- } ;
378-
379- let is_param = ast:: Param :: can_cast ( parent. kind ( ) ) ;
380-
381- // We have to check that it's either `let var = ...` or `var @ Variant(_)` statement,
382- // because e.g. match arms are patterns as well.
383- // In other words, we check that it's a named variable binding.
384- let is_binding = ast:: LetStmt :: can_cast ( parent. kind ( ) )
385- || ( ast:: MatchArm :: can_cast ( parent. kind ( ) )
386- && ident_pat. at_token ( ) . is_some ( ) ) ;
387- if !( is_param || is_binding) {
388- // This pattern is not an actual variable declaration, e.g. `Some(val) => {..}` match arm.
389- continue ;
390- }
391-
392- let ident_type =
393- if is_param { IdentType :: Parameter } else { IdentType :: Variable } ;
356+ let Ok ( source_ptr) = source_map. pat_syntax ( id) else {
357+ continue ;
358+ } ;
359+ let Some ( ptr) = source_ptr. value . cast :: < ast:: IdentPat > ( ) else {
360+ continue ;
361+ } ;
362+ let root = source_ptr. file_syntax ( self . db . upcast ( ) ) ;
363+ let ident_pat = ptr. to_node ( & root) ;
364+ let Some ( parent) = ident_pat. syntax ( ) . parent ( ) else {
365+ continue ;
366+ } ;
394367
395- self . create_incorrect_case_diagnostic_for_ast_node (
396- replacement,
397- source_ptr. file_id ,
398- & ident_pat,
399- ident_type,
400- ) ;
401- }
368+ let is_param = ast:: Param :: can_cast ( parent. kind ( ) ) ;
369+ // We have to check that it's either `let var = ...` or `var @ Variant(_)` statement,
370+ // because e.g. match arms are patterns as well.
371+ // In other words, we check that it's a named variable binding.
372+ let is_binding = ast:: LetStmt :: can_cast ( parent. kind ( ) )
373+ || ( ast:: MatchArm :: can_cast ( parent. kind ( ) ) && ident_pat. at_token ( ) . is_some ( ) ) ;
374+ if !( is_param || is_binding) {
375+ // This pattern is not an actual variable declaration, e.g. `Some(val) => {..}` match arm.
376+ continue ;
402377 }
378+
379+ let ident_type = if is_param { IdentType :: Parameter } else { IdentType :: Variable } ;
380+
381+ self . create_incorrect_case_diagnostic_for_ast_node (
382+ replacement,
383+ source_ptr. file_id ,
384+ & ident_pat,
385+ ident_type,
386+ ) ;
403387 }
404388 }
405389
0 commit comments