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..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::{
7use crate::{ 7use crate::{
8 ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams}, 8 ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams},
9 Assist, AssistCtx, AssistId, 9 Assist, AssistCtx, AssistId,
10 utils::{get_missing_impl_items, resolve_target_trait},
10}; 11};
11 12
12#[derive(PartialEq)] 13#[derive(PartialEq)]
@@ -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,20 +117,23 @@ 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(),
129 AddMissingImplMembersMode::NoDefaultMethods => def.body().is_none(), 131 AddMissingImplMembersMode::NoDefaultMethods => def.body().is_none(),
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::*;