Skip to content

Commit de1fc70

Browse files
committed
internal: refactor find_map diagnostic
1 parent 24262f9 commit de1fc70

File tree

6 files changed

+192
-193
lines changed

6 files changed

+192
-193
lines changed

crates/hir/src/diagnostics.rs

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ diagnostics![
4141
MissingUnsafe,
4242
NoSuchField,
4343
RemoveThisSemicolon,
44+
ReplaceFilterMapNextWithFindMap,
4445
UnimplementedBuiltinMacro,
4546
UnresolvedExternCrate,
4647
UnresolvedImport,
@@ -121,31 +122,13 @@ pub struct MissingFields {
121122
pub missed_fields: Vec<Name>,
122123
}
123124

124-
// Diagnostic: replace-filter-map-next-with-find-map
125-
//
126-
// This diagnostic is triggered when `.filter_map(..).next()` is used, rather than the more concise `.find_map(..)`.
127125
#[derive(Debug)]
128126
pub struct ReplaceFilterMapNextWithFindMap {
129127
pub file: HirFileId,
130128
/// This expression is the whole method chain up to and including `.filter_map(..).next()`.
131129
pub next_expr: AstPtr<ast::Expr>,
132130
}
133131

134-
impl Diagnostic for ReplaceFilterMapNextWithFindMap {
135-
fn code(&self) -> DiagnosticCode {
136-
DiagnosticCode("replace-filter-map-next-with-find-map")
137-
}
138-
fn message(&self) -> String {
139-
"replace filter_map(..).next() with find_map(..)".to_string()
140-
}
141-
fn display_source(&self) -> InFile<SyntaxNodePtr> {
142-
InFile { file_id: self.file, value: self.next_expr.clone().into() }
143-
}
144-
fn as_any(&self) -> &(dyn Any + Send + 'static) {
145-
self
146-
}
147-
}
148-
149132
#[derive(Debug)]
150133
pub struct MismatchedArgCount {
151134
pub call_expr: InFile<AstPtr<ast::Expr>>,

crates/hir/src/lib.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,10 +1168,13 @@ impl Function {
11681168
}
11691169
BodyValidationDiagnostic::ReplaceFilterMapNextWithFindMap { method_call_expr } => {
11701170
if let Ok(next_source_ptr) = source_map.expr_syntax(method_call_expr) {
1171-
sink.push(ReplaceFilterMapNextWithFindMap {
1172-
file: next_source_ptr.file_id,
1173-
next_expr: next_source_ptr.value,
1174-
});
1171+
acc.push(
1172+
ReplaceFilterMapNextWithFindMap {
1173+
file: next_source_ptr.file_id,
1174+
next_expr: next_source_ptr.value,
1175+
}
1176+
.into(),
1177+
);
11751178
}
11761179
}
11771180
BodyValidationDiagnostic::MismatchedArgCount { call_expr, expected, found } => {

crates/ide/src/diagnostics.rs

Lines changed: 2 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ mod missing_ok_or_some_in_tail_expr;
1313
mod missing_unsafe;
1414
mod no_such_field;
1515
mod remove_this_semicolon;
16+
mod replace_filter_map_next_with_find_map;
1617
mod unimplemented_builtin_macro;
1718
mod unresolved_extern_crate;
1819
mod unresolved_import;
@@ -167,9 +168,6 @@ pub(crate) fn diagnostics(
167168
.on::<hir::diagnostics::IncorrectCase, _>(|d| {
168169
res.borrow_mut().push(warning_with_fix(d, &sema, resolve));
169170
})
170-
.on::<hir::diagnostics::ReplaceFilterMapNextWithFindMap, _>(|d| {
171-
res.borrow_mut().push(warning_with_fix(d, &sema, resolve));
172-
})
173171
.on::<UnlinkedFile, _>(|d| {
174172
// Limit diagnostic to the first few characters in the file. This matches how VS Code
175173
// renders it with the full span, but on other editors, and is less invasive.
@@ -225,6 +223,7 @@ pub(crate) fn diagnostics(
225223
AnyDiagnostic::MissingUnsafe(d) => missing_unsafe::missing_unsafe(&ctx, &d),
226224
AnyDiagnostic::NoSuchField(d) => no_such_field::no_such_field(&ctx, &d),
227225
AnyDiagnostic::RemoveThisSemicolon(d) => remove_this_semicolon::remove_this_semicolon(&ctx, &d),
226+
AnyDiagnostic::ReplaceFilterMapNextWithFindMap(d) => replace_filter_map_next_with_find_map::replace_filter_map_next_with_find_map(&ctx, &d),
228227
AnyDiagnostic::UnimplementedBuiltinMacro(d) => unimplemented_builtin_macro::unimplemented_builtin_macro(&ctx, &d),
229228
AnyDiagnostic::UnresolvedExternCrate(d) => unresolved_extern_crate::unresolved_extern_crate(&ctx, &d),
230229
AnyDiagnostic::UnresolvedImport(d) => unresolved_import::unresolved_import(&ctx, &d),
@@ -672,89 +671,6 @@ mod foo;
672671
);
673672
}
674673

675-
// Register the required standard library types to make the tests work
676-
fn add_filter_map_with_find_next_boilerplate(body: &str) -> String {
677-
let prefix = r#"
678-
//- /main.rs crate:main deps:core
679-
use core::iter::Iterator;
680-
use core::option::Option::{self, Some, None};
681-
"#;
682-
let suffix = r#"
683-
//- /core/lib.rs crate:core
684-
pub mod option {
685-
pub enum Option<T> { Some(T), None }
686-
}
687-
pub mod iter {
688-
pub trait Iterator {
689-
type Item;
690-
fn filter_map<B, F>(self, f: F) -> FilterMap where F: FnMut(Self::Item) -> Option<B> { FilterMap }
691-
fn next(&mut self) -> Option<Self::Item>;
692-
}
693-
pub struct FilterMap {}
694-
impl Iterator for FilterMap {
695-
type Item = i32;
696-
fn next(&mut self) -> i32 { 7 }
697-
}
698-
}
699-
"#;
700-
format!("{}{}{}", prefix, body, suffix)
701-
}
702-
703-
#[test]
704-
fn replace_filter_map_next_with_find_map2() {
705-
check_diagnostics(&add_filter_map_with_find_next_boilerplate(
706-
r#"
707-
fn foo() {
708-
let m = [1, 2, 3].iter().filter_map(|x| if *x == 2 { Some (4) } else { None }).next();
709-
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ replace filter_map(..).next() with find_map(..)
710-
}
711-
"#,
712-
));
713-
}
714-
715-
#[test]
716-
fn replace_filter_map_next_with_find_map_no_diagnostic_without_next() {
717-
check_diagnostics(&add_filter_map_with_find_next_boilerplate(
718-
r#"
719-
fn foo() {
720-
let m = [1, 2, 3]
721-
.iter()
722-
.filter_map(|x| if *x == 2 { Some (4) } else { None })
723-
.len();
724-
}
725-
"#,
726-
));
727-
}
728-
729-
#[test]
730-
fn replace_filter_map_next_with_find_map_no_diagnostic_with_intervening_methods() {
731-
check_diagnostics(&add_filter_map_with_find_next_boilerplate(
732-
r#"
733-
fn foo() {
734-
let m = [1, 2, 3]
735-
.iter()
736-
.filter_map(|x| if *x == 2 { Some (4) } else { None })
737-
.map(|x| x + 2)
738-
.len();
739-
}
740-
"#,
741-
));
742-
}
743-
744-
#[test]
745-
fn replace_filter_map_next_with_find_map_no_diagnostic_if_not_in_chain() {
746-
check_diagnostics(&add_filter_map_with_find_next_boilerplate(
747-
r#"
748-
fn foo() {
749-
let m = [1, 2, 3]
750-
.iter()
751-
.filter_map(|x| if *x == 2 { Some (4) } else { None });
752-
let n = m.next();
753-
}
754-
"#,
755-
));
756-
}
757-
758674
#[test]
759675
fn missing_record_pat_field_no_diagnostic_if_not_exhaustive() {
760676
check_diagnostics(

crates/ide/src/diagnostics/fixes.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! Provides a way to attach fixes to the diagnostics.
22
//! The same module also has all curret custom fixes for the diagnostics implemented.
33
mod change_case;
4-
mod replace_with_find_map;
54

65
use hir::{diagnostics::Diagnostic, Semantics};
76
use ide_assists::AssistResolveStrategy;

crates/ide/src/diagnostics/fixes/replace_with_find_map.rs

Lines changed: 0 additions & 84 deletions
This file was deleted.

0 commit comments

Comments
 (0)