aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src/handlers
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_assists/src/handlers')
-rw-r--r--crates/ra_assists/src/handlers/add_missing_impl_members.rs47
1 files changed, 14 insertions, 33 deletions
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..ab21388c8 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 @@
1use hir::{db::HirDatabase, HasSource, InFile}; 1use hir::{HasSource, InFile};
2use ra_syntax::{ 2use ra_syntax::{
3 ast::{self, edit, make, AstNode, NameOwner}, 3 ast::{self, edit, make, AstNode, NameOwner},
4 SmolStr, 4 SmolStr,
@@ -6,6 +6,7 @@ use ra_syntax::{
6 6
7use crate::{ 7use crate::{
8 ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams}, 8 ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams},
9 utils::{get_missing_impl_items, resolve_target_trait},
9 Assist, AssistCtx, AssistId, 10 Assist, AssistCtx, AssistId,
10}; 11};
11 12
@@ -103,11 +104,9 @@ fn add_missing_impl_members_inner(
103 let impl_node = ctx.find_node_at_offset::<ast::ImplBlock>()?; 104 let impl_node = ctx.find_node_at_offset::<ast::ImplBlock>()?;
104 let impl_item_list = impl_node.item_list()?; 105 let impl_item_list = impl_node.item_list()?;
105 106
106 let (trait_, trait_def) = { 107 let analyzer = ctx.source_analyzer(impl_node.syntax(), None);
107 let analyzer = ctx.source_analyzer(impl_node.syntax(), None);
108 108
109 resolve_target_trait_def(ctx.db, &analyzer, &impl_node)? 109 let trait_ = resolve_target_trait(ctx.db, &analyzer, &impl_node)?;
110 };
111 110
112 let def_name = |item: &ast::ImplItem| -> Option<SmolStr> { 111 let def_name = |item: &ast::ImplItem| -> Option<SmolStr> {
113 match item { 112 match item {
@@ -118,11 +117,14 @@ fn add_missing_impl_members_inner(
118 .map(|it| it.text().clone()) 117 .map(|it| it.text().clone())
119 }; 118 };
120 119
121 let trait_items = trait_def.item_list()?.impl_items(); 120 let missing_items = get_missing_impl_items(ctx.db, &analyzer, &impl_node)
122 let impl_items = impl_item_list.impl_items().collect::<Vec<_>>(); 121 .iter()
123 122 .map(|i| match i {
124 let missing_items: Vec<_> = trait_items 123 hir::AssocItem::Function(i) => ast::ImplItem::FnDef(i.source(ctx.db).value),
125 .filter(|t| def_name(t).is_some()) 124 hir::AssocItem::TypeAlias(i) => ast::ImplItem::TypeAliasDef(i.source(ctx.db).value),
125 hir::AssocItem::Const(i) => ast::ImplItem::ConstDef(i.source(ctx.db).value),
126 })
127 .filter(|t| def_name(&t).is_some())
126 .filter(|t| match t { 128 .filter(|t| match t {
127 ast::ImplItem::FnDef(def) => match mode { 129 ast::ImplItem::FnDef(def) => match mode {
128 AddMissingImplMembersMode::DefaultMethodsOnly => def.body().is_some(), 130 AddMissingImplMembersMode::DefaultMethodsOnly => def.body().is_some(),
@@ -130,8 +132,8 @@ fn add_missing_impl_members_inner(
130 }, 132 },
131 _ => mode == AddMissingImplMembersMode::NoDefaultMethods, 133 _ => mode == AddMissingImplMembersMode::NoDefaultMethods,
132 }) 134 })
133 .filter(|t| impl_items.iter().all(|i| def_name(i) != def_name(t))) 135 .collect::<Vec<_>>();
134 .collect(); 136
135 if missing_items.is_empty() { 137 if missing_items.is_empty() {
136 return None; 138 return None;
137 } 139 }
@@ -177,27 +179,6 @@ fn add_body(fn_def: ast::FnDef) -> ast::FnDef {
177 } 179 }
178} 180}
179 181
180/// Given an `ast::ImplBlock`, resolves the target trait (the one being
181/// implemented) to a `ast::TraitDef`.
182fn resolve_target_trait_def(
183 db: &impl HirDatabase,
184 analyzer: &hir::SourceAnalyzer,
185 impl_block: &ast::ImplBlock,
186) -> Option<(hir::Trait, ast::TraitDef)> {
187 let ast_path = impl_block
188 .target_trait()
189 .map(|it| it.syntax().clone())
190 .and_then(ast::PathType::cast)?
191 .path()?;
192
193 match analyzer.resolve_path(db, &ast_path) {
194 Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => {
195 Some((def, def.source(db).value))
196 }
197 _ => None,
198 }
199}
200
201#[cfg(test)] 182#[cfg(test)]
202mod tests { 183mod tests {
203 use super::*; 184 use super::*;