From d85abd77b98ff5925621c18f2ffe121640d17c80 Mon Sep 17 00:00:00 2001 From: Kevin DeLorey <2295721+kdelorey@users.noreply.github.com> Date: Sun, 9 Feb 2020 12:24:34 -0600 Subject: Added a utility function that can be used to determine the missing impl items. --- crates/ra_assists/src/lib.rs | 2 +- crates/ra_assists/src/utils.rs | 77 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 76 insertions(+), 3 deletions(-) (limited to 'crates/ra_assists/src') diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 828a8e9e8..cb124eaf0 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs @@ -9,7 +9,7 @@ mod assist_ctx; mod marks; #[cfg(test)] mod doc_tests; -mod utils; +pub mod utils; pub mod ast_transform; use ra_db::FileRange; diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs index 0d5722295..7bc21c6e4 100644 --- a/crates/ra_assists/src/utils.rs +++ b/crates/ra_assists/src/utils.rs @@ -1,10 +1,83 @@ //! Assorted functions shared by several assists. use ra_syntax::{ - ast::{self, make}, - T, + ast::{self, make, NameOwner}, + AstNode, T, }; +use hir::db::HirDatabase; + +use rustc_hash::FxHashSet; + +pub fn get_missing_impl_items( + db: &impl HirDatabase, + analyzer: &hir::SourceAnalyzer, + impl_block: &ast::ImplBlock, +) -> Vec { + // since the names are unique only to each associated type (fn/type/const), + // create buckets of each already implemented type that we'll use in the + // lookup later. + let mut impl_fns = FxHashSet::default(); + let mut impl_type = FxHashSet::default(); + let mut impl_const = FxHashSet::default(); + + if let Some(item_list) = impl_block.item_list() { + for item in item_list.impl_items() { + match item { + ast::ImplItem::FnDef(f) => { + if let Some(n) = f.name() { + impl_fns.insert(n.syntax().to_string()); + } + } + + ast::ImplItem::TypeAliasDef(t) => { + if let Some(n) = t.name() { + impl_type.insert(n.syntax().to_string()); + } + } + + ast::ImplItem::ConstDef(c) => { + if let Some(n) = c.name() { + impl_const.insert(n.syntax().to_string()); + } + } + } + } + } + + resolve_target_trait(db, analyzer, impl_block).map_or(vec![], |target_trait| { + target_trait + .items(db) + .iter() + .filter(|i| match i { + hir::AssocItem::Function(f) => !impl_fns.contains(&f.name(db).to_string()), + hir::AssocItem::TypeAlias(t) => !impl_type.contains(&t.name(db).to_string()), + hir::AssocItem::Const(c) => { + c.name(db).map(|n| !impl_const.contains(&n.to_string())).unwrap_or_default() + } + }) + .map(|i| i.clone()) + .collect() + }) +} + +fn resolve_target_trait( + db: &impl HirDatabase, + analyzer: &hir::SourceAnalyzer, + impl_block: &ast::ImplBlock, +) -> Option { + let ast_path = impl_block + .target_trait() + .map(|it| it.syntax().clone()) + .and_then(ast::PathType::cast)? + .path()?; + + match analyzer.resolve_path(db, &ast_path) { + Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def), + _ => None, + } +} + pub(crate) fn invert_boolean_expression(expr: ast::Expr) -> ast::Expr { if let Some(expr) = invert_special_case(&expr) { return expr; -- cgit v1.2.3 From f0f242cb4f9ee49427b03af21c31239e8132ac96 Mon Sep 17 00:00:00 2001 From: Kevin DeLorey <2295721+kdelorey@users.noreply.github.com> Date: Mon, 10 Feb 2020 21:09:04 -0600 Subject: Adjusted the hashset buckets to lump functions/consts together as their names must be unique. --- crates/ra_assists/src/utils.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'crates/ra_assists/src') diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs index 7bc21c6e4..660da3645 100644 --- a/crates/ra_assists/src/utils.rs +++ b/crates/ra_assists/src/utils.rs @@ -9,24 +9,25 @@ use hir::db::HirDatabase; use rustc_hash::FxHashSet; +/// Generate a collection of associated items that are missing from a +/// `impl Trait for` block. pub fn get_missing_impl_items( db: &impl HirDatabase, analyzer: &hir::SourceAnalyzer, impl_block: &ast::ImplBlock, ) -> Vec { - // since the names are unique only to each associated type (fn/type/const), - // create buckets of each already implemented type that we'll use in the - // lookup later. - let mut impl_fns = FxHashSet::default(); + + // Names must be unique between constants and functions. However, type aliases + // may share the same name as a function or constant. + let mut impl_fns_consts = FxHashSet::default(); let mut impl_type = FxHashSet::default(); - let mut impl_const = FxHashSet::default(); if let Some(item_list) = impl_block.item_list() { for item in item_list.impl_items() { match item { ast::ImplItem::FnDef(f) => { if let Some(n) = f.name() { - impl_fns.insert(n.syntax().to_string()); + impl_fns_consts.insert(n.syntax().to_string()); } } @@ -38,7 +39,7 @@ pub fn get_missing_impl_items( ast::ImplItem::ConstDef(c) => { if let Some(n) = c.name() { - impl_const.insert(n.syntax().to_string()); + impl_fns_consts.insert(n.syntax().to_string()); } } } @@ -50,10 +51,10 @@ pub fn get_missing_impl_items( .items(db) .iter() .filter(|i| match i { - hir::AssocItem::Function(f) => !impl_fns.contains(&f.name(db).to_string()), + hir::AssocItem::Function(f) => !impl_fns_consts.contains(&f.name(db).to_string()), hir::AssocItem::TypeAlias(t) => !impl_type.contains(&t.name(db).to_string()), hir::AssocItem::Const(c) => { - c.name(db).map(|n| !impl_const.contains(&n.to_string())).unwrap_or_default() + c.name(db).map(|n| !impl_fns_consts.contains(&n.to_string())).unwrap_or_default() } }) .map(|i| i.clone()) -- cgit v1.2.3 From ca43bb3ff787c17173a2a5d18f55eabb1bc5136b Mon Sep 17 00:00:00 2001 From: Kevin DeLorey <2295721+kdelorey@users.noreply.github.com> Date: Tue, 11 Feb 2020 06:57:26 -0600 Subject: Updated the `add_missing_impl_members` to use the shared utility. --- .../src/handlers/add_missing_impl_members.rs | 47 +++++++--------------- crates/ra_assists/src/utils.rs | 2 +- 2 files changed, 15 insertions(+), 34 deletions(-) (limited to 'crates/ra_assists/src') diff --git a/crates/ra_assists/src/handlers/add_missing_impl_members.rs b/crates/ra_assists/src/handlers/add_missing_impl_members.rs index 448697d31..495493a52 100644 --- a/crates/ra_assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ra_assists/src/handlers/add_missing_impl_members.rs @@ -7,6 +7,7 @@ use ra_syntax::{ use crate::{ ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams}, Assist, AssistCtx, AssistId, + utils::{get_missing_impl_items, resolve_target_trait}, }; #[derive(PartialEq)] @@ -103,11 +104,9 @@ fn add_missing_impl_members_inner( let impl_node = ctx.find_node_at_offset::()?; let impl_item_list = impl_node.item_list()?; - let (trait_, trait_def) = { - let analyzer = ctx.source_analyzer(impl_node.syntax(), None); + let analyzer = ctx.source_analyzer(impl_node.syntax(), None); - resolve_target_trait_def(ctx.db, &analyzer, &impl_node)? - }; + let trait_ = resolve_target_trait(ctx.db, &analyzer, &impl_node)?; let def_name = |item: &ast::ImplItem| -> Option { match item { @@ -118,20 +117,23 @@ fn add_missing_impl_members_inner( .map(|it| it.text().clone()) }; - let trait_items = trait_def.item_list()?.impl_items(); - let impl_items = impl_item_list.impl_items().collect::>(); - - let missing_items: Vec<_> = trait_items - .filter(|t| def_name(t).is_some()) + let missing_items = get_missing_impl_items(ctx.db, &analyzer, &impl_node) + .iter() + .map(|i| match i { + hir::AssocItem::Function(i) => ast::ImplItem::FnDef(i.source(ctx.db).value), + hir::AssocItem::TypeAlias(i) => ast::ImplItem::TypeAliasDef(i.source(ctx.db).value), + hir::AssocItem::Const(i) => ast::ImplItem::ConstDef(i.source(ctx.db).value), + }) + .filter(|t| def_name(&t).is_some()) .filter(|t| match t { ast::ImplItem::FnDef(def) => match mode { AddMissingImplMembersMode::DefaultMethodsOnly => def.body().is_some(), AddMissingImplMembersMode::NoDefaultMethods => def.body().is_none(), - }, + } _ => mode == AddMissingImplMembersMode::NoDefaultMethods, }) - .filter(|t| impl_items.iter().all(|i| def_name(i) != def_name(t))) - .collect(); + .collect::>(); + if missing_items.is_empty() { return None; } @@ -177,27 +179,6 @@ fn add_body(fn_def: ast::FnDef) -> ast::FnDef { } } -/// Given an `ast::ImplBlock`, resolves the target trait (the one being -/// implemented) to a `ast::TraitDef`. -fn resolve_target_trait_def( - db: &impl HirDatabase, - analyzer: &hir::SourceAnalyzer, - impl_block: &ast::ImplBlock, -) -> Option<(hir::Trait, ast::TraitDef)> { - let ast_path = impl_block - .target_trait() - .map(|it| it.syntax().clone()) - .and_then(ast::PathType::cast)? - .path()?; - - match analyzer.resolve_path(db, &ast_path) { - Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => { - Some((def, def.source(db).value)) - } - _ => None, - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs index 660da3645..7628933fb 100644 --- a/crates/ra_assists/src/utils.rs +++ b/crates/ra_assists/src/utils.rs @@ -62,7 +62,7 @@ pub fn get_missing_impl_items( }) } -fn resolve_target_trait( +pub(crate) fn resolve_target_trait( db: &impl HirDatabase, analyzer: &hir::SourceAnalyzer, impl_block: &ast::ImplBlock, -- cgit v1.2.3 From b4429a9d64759f4aee3cb48cb938da021a24b7b5 Mon Sep 17 00:00:00 2001 From: Kevin DeLorey <2295721+kdelorey@users.noreply.github.com> Date: Tue, 11 Feb 2020 07:10:06 -0600 Subject: Fixed warning generated after refactoring. --- crates/ra_assists/src/handlers/add_missing_impl_members.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/ra_assists/src') diff --git a/crates/ra_assists/src/handlers/add_missing_impl_members.rs b/crates/ra_assists/src/handlers/add_missing_impl_members.rs index 495493a52..4c937b154 100644 --- a/crates/ra_assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ra_assists/src/handlers/add_missing_impl_members.rs @@ -1,4 +1,4 @@ -use hir::{db::HirDatabase, HasSource, InFile}; +use hir::{HasSource, InFile}; use ra_syntax::{ ast::{self, edit, make, AstNode, NameOwner}, SmolStr, -- cgit v1.2.3 From 3aaf46afa13b6fcbfdc36d8eb0cce48196d824a7 Mon Sep 17 00:00:00 2001 From: Kevin DeLorey <2295721+kdelorey@users.noreply.github.com> Date: Tue, 11 Feb 2020 09:40:08 -0600 Subject: Formatted changes. --- crates/ra_assists/src/handlers/add_missing_impl_members.rs | 4 ++-- crates/ra_assists/src/utils.rs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'crates/ra_assists/src') diff --git a/crates/ra_assists/src/handlers/add_missing_impl_members.rs b/crates/ra_assists/src/handlers/add_missing_impl_members.rs index 4c937b154..ab21388c8 100644 --- a/crates/ra_assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ra_assists/src/handlers/add_missing_impl_members.rs @@ -6,8 +6,8 @@ use ra_syntax::{ use crate::{ ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams}, - Assist, AssistCtx, AssistId, utils::{get_missing_impl_items, resolve_target_trait}, + Assist, AssistCtx, AssistId, }; #[derive(PartialEq)] @@ -129,7 +129,7 @@ fn add_missing_impl_members_inner( ast::ImplItem::FnDef(def) => match mode { AddMissingImplMembersMode::DefaultMethodsOnly => def.body().is_some(), AddMissingImplMembersMode::NoDefaultMethods => def.body().is_none(), - } + }, _ => mode == AddMissingImplMembersMode::NoDefaultMethods, }) .collect::>(); diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs index 7628933fb..461f01536 100644 --- a/crates/ra_assists/src/utils.rs +++ b/crates/ra_assists/src/utils.rs @@ -9,14 +9,13 @@ use hir::db::HirDatabase; use rustc_hash::FxHashSet; -/// Generate a collection of associated items that are missing from a +/// Generate a collection of associated items that are missing from a /// `impl Trait for` block. pub fn get_missing_impl_items( db: &impl HirDatabase, analyzer: &hir::SourceAnalyzer, impl_block: &ast::ImplBlock, ) -> Vec { - // Names must be unique between constants and functions. However, type aliases // may share the same name as a function or constant. let mut impl_fns_consts = FxHashSet::default(); @@ -53,9 +52,10 @@ pub fn get_missing_impl_items( .filter(|i| match i { hir::AssocItem::Function(f) => !impl_fns_consts.contains(&f.name(db).to_string()), hir::AssocItem::TypeAlias(t) => !impl_type.contains(&t.name(db).to_string()), - hir::AssocItem::Const(c) => { - c.name(db).map(|n| !impl_fns_consts.contains(&n.to_string())).unwrap_or_default() - } + hir::AssocItem::Const(c) => c + .name(db) + .map(|n| !impl_fns_consts.contains(&n.to_string())) + .unwrap_or_default(), }) .map(|i| i.clone()) .collect() -- cgit v1.2.3 From e664cd73e3f91086dc765fb5ec74ebec2daa8ffa Mon Sep 17 00:00:00 2001 From: Kevin DeLorey <2295721+kdelorey@users.noreply.github.com> Date: Tue, 11 Feb 2020 09:48:26 -0600 Subject: Removed doc comments entirely from the changes. --- crates/ra_assists/src/utils.rs | 2 -- 1 file changed, 2 deletions(-) (limited to 'crates/ra_assists/src') diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs index 461f01536..1280a4fdc 100644 --- a/crates/ra_assists/src/utils.rs +++ b/crates/ra_assists/src/utils.rs @@ -9,8 +9,6 @@ use hir::db::HirDatabase; use rustc_hash::FxHashSet; -/// Generate a collection of associated items that are missing from a -/// `impl Trait for` block. pub fn get_missing_impl_items( db: &impl HirDatabase, analyzer: &hir::SourceAnalyzer, -- cgit v1.2.3 From 47d314e85681c075ff859e13343927e7406e1b46 Mon Sep 17 00:00:00 2001 From: Kevin DeLorey <2295721+kdelorey@users.noreply.github.com> Date: Tue, 11 Feb 2020 10:04:30 -0600 Subject: Fixing minor suggestions and added module level documentation. --- crates/ra_assists/src/utils.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'crates/ra_assists/src') diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs index 1280a4fdc..6ff44c95c 100644 --- a/crates/ra_assists/src/utils.rs +++ b/crates/ra_assists/src/utils.rs @@ -6,7 +6,6 @@ use ra_syntax::{ }; use hir::db::HirDatabase; - use rustc_hash::FxHashSet; pub fn get_missing_impl_items( @@ -55,7 +54,7 @@ pub fn get_missing_impl_items( .map(|n| !impl_fns_consts.contains(&n.to_string())) .unwrap_or_default(), }) - .map(|i| i.clone()) + .cloned() .collect() }) } -- cgit v1.2.3