mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 06:41:48 +00:00
Identify methods using functions ids rather than string names
This commit is contained in:
parent
920e57bd15
commit
8c7ccdc29d
3 changed files with 31 additions and 7 deletions
|
@ -304,6 +304,7 @@ pub use hir_expand::name as __name;
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! __known_path {
|
macro_rules! __known_path {
|
||||||
(core::iter::IntoIterator) => {};
|
(core::iter::IntoIterator) => {};
|
||||||
|
(core::iter::Iterator) => {};
|
||||||
(core::result::Result) => {};
|
(core::result::Result) => {};
|
||||||
(core::option::Option) => {};
|
(core::option::Option) => {};
|
||||||
(core::ops::Range) => {};
|
(core::ops::Range) => {};
|
||||||
|
|
|
@ -186,6 +186,9 @@ pub mod known {
|
||||||
Neg,
|
Neg,
|
||||||
Not,
|
Not,
|
||||||
Index,
|
Index,
|
||||||
|
// Components of known path (function name)
|
||||||
|
filter_map,
|
||||||
|
next,
|
||||||
// Builtin macros
|
// Builtin macros
|
||||||
file,
|
file,
|
||||||
column,
|
column,
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use hir_def::{expr::Statement, path::path, resolver::HasResolver, AdtId, DefWithBodyId};
|
use hir_def::{AdtId, AssocItemId, DefWithBodyId, expr::Statement, path::path, resolver::HasResolver};
|
||||||
use hir_expand::diagnostics::DiagnosticSink;
|
use hir_expand::{diagnostics::DiagnosticSink, name};
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use syntax::{ast, AstPtr};
|
use syntax::{ast, AstPtr};
|
||||||
|
|
||||||
|
@ -155,19 +155,39 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_for_filter_map_next(&mut self, db: &dyn HirDatabase) {
|
fn check_for_filter_map_next(&mut self, db: &dyn HirDatabase) {
|
||||||
|
// Find the FunctionIds for Iterator::filter_map and Iterator::next
|
||||||
|
let iterator_path = path![core::iter::Iterator];
|
||||||
|
let resolver = self.owner.resolver(db.upcast());
|
||||||
|
let iterator_trait_id = match resolver.resolve_known_trait(db.upcast(), &iterator_path) {
|
||||||
|
Some(id) => id,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
let iterator_trait_items = &db.trait_data(iterator_trait_id).items;
|
||||||
|
let filter_map_function_id = match iterator_trait_items.iter().find(|item| item.0 == name![filter_map]) {
|
||||||
|
Some((_, AssocItemId::FunctionId(id))) => id,
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
let next_function_id = match iterator_trait_items.iter().find(|item| item.0 == name![next]) {
|
||||||
|
Some((_, AssocItemId::FunctionId(id))) => id,
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Search function body for instances of .filter_map(..).next()
|
||||||
let body = db.body(self.owner.into());
|
let body = db.body(self.owner.into());
|
||||||
let mut prev = None;
|
let mut prev = None;
|
||||||
|
|
||||||
for (id, expr) in body.exprs.iter() {
|
for (id, expr) in body.exprs.iter() {
|
||||||
if let Expr::MethodCall { receiver, method_name, args, .. } = expr {
|
if let Expr::MethodCall { receiver, .. } = expr {
|
||||||
let method_name = format!("{}", method_name);
|
let function_id = match self.infer.method_resolution(id) {
|
||||||
|
Some(id) => id,
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
|
||||||
if method_name == "filter_map" && args.len() == 1 {
|
if function_id == *filter_map_function_id {
|
||||||
prev = Some(id);
|
prev = Some(id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if method_name == "next" {
|
if function_id == *next_function_id {
|
||||||
if let Some(filter_map_id) = prev {
|
if let Some(filter_map_id) = prev {
|
||||||
if *receiver == filter_map_id {
|
if *receiver == filter_map_id {
|
||||||
let (_, source_map) = db.body_with_source_map(self.owner.into());
|
let (_, source_map) = db.body_with_source_map(self.owner.into());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue