Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-assists/src/handlers/generate_trait_from_impl.rs')
| -rw-r--r-- | crates/ide-assists/src/handlers/generate_trait_from_impl.rs | 49 |
1 files changed, 34 insertions, 15 deletions
diff --git a/crates/ide-assists/src/handlers/generate_trait_from_impl.rs b/crates/ide-assists/src/handlers/generate_trait_from_impl.rs index d085ff3c20..12afd9ae6a 100644 --- a/crates/ide-assists/src/handlers/generate_trait_from_impl.rs +++ b/crates/ide-assists/src/handlers/generate_trait_from_impl.rs @@ -1,7 +1,7 @@ use crate::assist_context::{AssistContext, Assists}; use ide_db::{assists::AssistId, defs::Definition, search::SearchScope}; use syntax::{ - AstNode, AstToken, SyntaxKind, T, TextRange, + AstNode, AstToken, SyntaxKind, T, ast::{ self, HasDocComments, HasGenericParams, HasName, HasVisibility, edit::AstNodeEdit, syntax_factory::SyntaxFactory, @@ -173,22 +173,15 @@ fn used_params( make: &SyntaxFactory, ctx: &AssistContext<'_, '_>, ) -> Option<ast::GenericParamList> { - let item_in_trait_range = |item| match item { - ast::AssocItem::Const(_) | ast::AssocItem::MacroCall(_) | ast::AssocItem::TypeAlias(_) => { - item.syntax().text_range() - } - ast::AssocItem::Fn(fn_item) => { - let range = fn_item.syntax().text_range(); - fn_item.body().map_or(range, |body| { - TextRange::new(range.start(), body.syntax().text_range().start()) - }) - } - }; - let trait_ranges = impl_ast + let impl_only_ranges = impl_ast .assoc_item_list() .into_iter() .flat_map(|list| list.assoc_items()) - .map(item_in_trait_range) + .filter_map(|item| match item { + ast::AssocItem::Fn(f) => Some(f.body()?.syntax().text_range()), + _ => None, + }) + .chain(impl_ast.self_ty().map(|it| it.syntax().text_range())) .collect::<Vec<_>>(); let used_in_impl = |param: &ast::GenericParam| { let Some(def) = ctx.sema.to_def(param) else { return true }; @@ -197,7 +190,7 @@ fn used_params( .in_scope(&SearchScope::single_file(ctx.file_id())) .all() .file_ranges() - .any(|it| trait_ranges.iter().any(|range| range.contains_range(it.range))) + .any(|it| !impl_only_ranges.iter().any(|range| range.contains_range(it.range))) }; let params = impl_ast.generic_param_list()?; let mut params = params.generic_params().filter(used_in_impl).peekable(); @@ -481,6 +474,32 @@ impl<T, const N: usize> SpecLen<T, N> for Foo<T, N> { } "#, ); + + check_assist_no_snippet_cap( + generate_trait_from_impl, + r#" +struct Foo<T, const N: usize>([T; N]); + +impl<T, const N: usize> F$0oo<T, N> where T: Copy { + fn spec_len(&self) -> usize { + 0 + } +} + "#, + r#" +struct Foo<T, const N: usize>([T; N]); + +trait SpecLen<T> where T: Copy { + fn spec_len(&self) -> usize; +} + +impl<T, const N: usize> SpecLen<T> for Foo<T, N> where T: Copy { + fn spec_len(&self) -> usize { + 0 + } +} + "#, + ); } #[test] |