@@ -16,12 +16,9 @@ mod case_conv;
16
16
use std:: fmt;
17
17
18
18
use 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 ,
25
22
} ;
26
23
use hir_expand:: {
27
24
name:: { AsName , Name } ,
@@ -298,11 +295,9 @@ impl<'a> DeclValidator<'a> {
298
295
return ;
299
296
}
300
297
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
-
304
298
// 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) {
306
301
let data = self . db . function_data ( func) ;
307
302
self . create_incorrect_case_diagnostic_for_item_name (
308
303
func,
@@ -315,91 +310,80 @@ impl<'a> DeclValidator<'a> {
315
310
}
316
311
317
312
// 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
+
320
323
let body = self . db . body ( func. into ( ) ) ;
321
- let pats_replacements = body
324
+ let mut pats_replacements = body
322
325
. pats
323
326
. iter ( )
324
327
. filter_map ( |( pat_id, pat) | match pat {
325
328
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.
328
330
if is_trait_impl_assoc_fn
329
331
&& body. params . iter ( ) . any ( |param_id| * param_id == pat_id)
330
332
{
331
333
cov_mark:: hit!( trait_impl_assoc_func_param_incorrect_case_ignored) ;
332
334
None
333
335
} 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) )
335
343
}
336
344
}
337
345
_ => None ,
338
346
} )
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 ( ) ;
354
348
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
- ) {
362
349
// 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 ( ) {
364
351
return ;
365
352
}
366
353
367
354
let ( _, source_map) = self . db . body_with_source_map ( func. into ( ) ) ;
368
-
369
355
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
+ } ;
394
367
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 ;
402
377
}
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
+ ) ;
403
387
}
404
388
}
405
389
0 commit comments