Skip to content

Commit 8e29104

Browse files
committed
refactor hir-ty::diagnostics::decl_check for struct fields
1 parent 23aa872 commit 8e29104

File tree

1 file changed

+57
-69
lines changed

1 file changed

+57
-69
lines changed

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

Lines changed: 57 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -388,14 +388,11 @@ impl<'a> DeclValidator<'a> {
388388
}
389389

390390
fn validate_struct(&mut self, struct_id: StructId) {
391-
let data = self.db.struct_data(struct_id);
392-
391+
// Check the structure name.
393392
let non_camel_case_allowed =
394393
self.allowed(struct_id.into(), allow::NON_CAMEL_CASE_TYPES, false);
395-
let non_snake_case_allowed = self.allowed(struct_id.into(), allow::NON_SNAKE_CASE, false);
396-
397-
// Check the structure name.
398394
if !non_camel_case_allowed {
395+
let data = self.db.struct_data(struct_id);
399396
self.create_incorrect_case_diagnostic_for_item_name(
400397
struct_id,
401398
&data.name,
@@ -405,88 +402,79 @@ impl<'a> DeclValidator<'a> {
405402
}
406403

407404
// Check the field names.
408-
let mut struct_fields_replacements = Vec::new();
409-
if !non_snake_case_allowed {
410-
if let VariantData::Record(fields) = data.variant_data.as_ref() {
411-
for (_, field) in fields.iter() {
412-
let field_name = field.name.display(self.db.upcast()).to_string();
413-
if let Some(new_name) = to_lower_snake_case(&field_name) {
414-
let replacement = Replacement {
415-
current_name: field.name.clone(),
416-
suggested_text: new_name,
417-
expected_case: CaseType::LowerSnakeCase,
418-
};
419-
struct_fields_replacements.push(replacement);
420-
}
421-
}
422-
}
405+
self.validate_struct_fields(struct_id);
406+
}
407+
408+
/// Check incorrect names for struct fields.
409+
fn validate_struct_fields(&mut self, struct_id: StructId) {
410+
if self.allowed(struct_id.into(), allow::NON_SNAKE_CASE, false) {
411+
return;
423412
}
424413

425-
// If there is at least one element to spawn a warning on, go to the source map and generate a warning.
426-
self.create_incorrect_case_diagnostic_for_struct_fields(
427-
struct_id,
428-
struct_fields_replacements,
429-
);
430-
}
414+
let data = self.db.struct_data(struct_id);
415+
let VariantData::Record(fields) = data.variant_data.as_ref() else {
416+
return;
417+
};
418+
let mut struct_fields_replacements = fields
419+
.iter()
420+
.filter_map(|(_, field)| {
421+
to_lower_snake_case(&field.name.to_smol_str()).map(|new_name| Replacement {
422+
current_name: field.name.clone(),
423+
suggested_text: new_name,
424+
expected_case: CaseType::LowerSnakeCase,
425+
})
426+
})
427+
.peekable();
431428

432-
/// Given the information about incorrect names for struct fields,
433-
/// looks up into the source code for exact locations and adds diagnostics into the sink.
434-
fn create_incorrect_case_diagnostic_for_struct_fields(
435-
&mut self,
436-
struct_id: StructId,
437-
struct_fields_replacements: Vec<Replacement>,
438-
) {
439429
// XXX: Only look at sources if we do have incorrect names.
440-
if struct_fields_replacements.is_empty() {
430+
if struct_fields_replacements.peek().is_none() {
441431
return;
442432
}
443433

444434
let struct_loc = struct_id.lookup(self.db.upcast());
445435
let struct_src = struct_loc.source(self.db.upcast());
446436

447-
let struct_fields_list = match struct_src.value.field_list() {
448-
Some(ast::FieldList::RecordFieldList(fields)) => fields,
449-
_ => {
450-
always!(
451-
struct_fields_replacements.is_empty(),
452-
"Replacements ({:?}) were generated for a structure fields which had no fields list: {:?}",
453-
struct_fields_replacements,
454-
struct_src
455-
);
456-
return;
457-
}
437+
let Some(ast::FieldList::RecordFieldList(struct_fields_list)) =
438+
struct_src.value.field_list()
439+
else {
440+
always!(
441+
struct_fields_replacements.peek().is_none(),
442+
"Replacements ({:?}) were generated for a structure fields \
443+
which had no fields list: {:?}",
444+
struct_fields_replacements.collect::<Vec<_>>(),
445+
struct_src
446+
);
447+
return;
458448
};
459449
let mut struct_fields_iter = struct_fields_list.fields();
460-
for field_to_rename in struct_fields_replacements {
450+
for field_replacement in struct_fields_replacements {
461451
// We assume that parameters in replacement are in the same order as in the
462452
// actual params list, but just some of them (ones that named correctly) are skipped.
463-
let ast_ptr = loop {
464-
match struct_fields_iter.next().and_then(|field| field.name()) {
465-
Some(field_name) => {
466-
if field_name.as_name() == field_to_rename.current_name {
467-
break field_name;
468-
}
469-
}
470-
None => {
471-
never!(
472-
"Replacement ({:?}) was generated for a structure field which was not found: {:?}",
473-
field_to_rename, struct_src
474-
);
475-
return;
453+
let field = loop {
454+
if let Some(field) = struct_fields_iter.next() {
455+
let Some(field_name) = field.name() else {
456+
continue;
457+
};
458+
if field_name.as_name() == field_replacement.current_name {
459+
break field;
476460
}
461+
} else {
462+
never!(
463+
"Replacement ({:?}) was generated for a structure field \
464+
which was not found: {:?}",
465+
field_replacement,
466+
struct_src
467+
);
468+
return;
477469
}
478470
};
479471

480-
let diagnostic = IncorrectCase {
481-
file: struct_src.file_id,
482-
ident_type: IdentType::Field,
483-
ident: AstPtr::new(&ast_ptr),
484-
expected_case: field_to_rename.expected_case,
485-
ident_text: field_to_rename.current_name.display(self.db.upcast()).to_string(),
486-
suggested_text: field_to_rename.suggested_text,
487-
};
488-
489-
self.sink.push(diagnostic);
472+
self.create_incorrect_case_diagnostic_for_ast_node(
473+
field_replacement,
474+
struct_src.file_id,
475+
&field,
476+
IdentType::Field,
477+
);
490478
}
491479
}
492480

0 commit comments

Comments
 (0)