diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir/src/lib.rs | 7 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/generate_is_empty_from_len.rs | 35 |
2 files changed, 33 insertions, 9 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index c5161dadd..1a1454068 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -1631,6 +1631,13 @@ impl Type { | |||
1631 | matches!(self.ty.value.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..)) | 1631 | matches!(self.ty.value.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..)) |
1632 | } | 1632 | } |
1633 | 1633 | ||
1634 | pub fn is_usize(&self) -> bool { | ||
1635 | matches!( | ||
1636 | self.ty.value.interned(&Interner), | ||
1637 | TyKind::Scalar(Scalar::Uint(hir_ty::primitive::UintTy::Usize)) | ||
1638 | ) | ||
1639 | } | ||
1640 | |||
1634 | pub fn remove_ref(&self) -> Option<Type> { | 1641 | pub fn remove_ref(&self) -> Option<Type> { |
1635 | match &self.ty.value.interned(&Interner) { | 1642 | match &self.ty.value.interned(&Interner) { |
1636 | TyKind::Ref(.., ty) => Some(self.derived(ty.clone())), | 1643 | TyKind::Ref(.., ty) => Some(self.derived(ty.clone())), |
diff --git a/crates/ide_assists/src/handlers/generate_is_empty_from_len.rs b/crates/ide_assists/src/handlers/generate_is_empty_from_len.rs index aa7072f25..b8834d283 100644 --- a/crates/ide_assists/src/handlers/generate_is_empty_from_len.rs +++ b/crates/ide_assists/src/handlers/generate_is_empty_from_len.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use hir::{known, HasSource, Name}; | 1 | use hir::{known, HasSource, Name}; |
2 | use syntax::{ | 2 | use syntax::{ |
3 | ast::{self, NameOwner}, | 3 | ast::{self, NameOwner}, |
4 | AstNode, TextRange, | 4 | AstNode, |
5 | }; | 5 | }; |
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
@@ -51,12 +51,19 @@ pub(crate) fn generate_is_empty_from_len(acc: &mut Assists, ctx: &AssistContext) | |||
51 | } | 51 | } |
52 | 52 | ||
53 | let impl_ = fn_node.syntax().ancestors().find_map(ast::Impl::cast)?; | 53 | let impl_ = fn_node.syntax().ancestors().find_map(ast::Impl::cast)?; |
54 | let len_fn = get_impl_method(ctx, &impl_, &known::len)?; | ||
55 | if !len_fn.ret_type(ctx.sema.db).is_usize() { | ||
56 | cov_mark::hit!(len_fn_different_return_type); | ||
57 | return None; | ||
58 | } | ||
59 | |||
54 | if get_impl_method(ctx, &impl_, &known::is_empty).is_some() { | 60 | if get_impl_method(ctx, &impl_, &known::is_empty).is_some() { |
55 | cov_mark::hit!(is_empty_already_implemented); | 61 | cov_mark::hit!(is_empty_already_implemented); |
56 | return None; | 62 | return None; |
57 | } | 63 | } |
58 | 64 | ||
59 | let range = get_text_range_of_len_function(ctx, &impl_)?; | 65 | let node = len_fn.source(ctx.sema.db)?; |
66 | let range = node.syntax().value.text_range(); | ||
60 | 67 | ||
61 | acc.add( | 68 | acc.add( |
62 | AssistId("generate_is_empty_from_len", AssistKind::Generate), | 69 | AssistId("generate_is_empty_from_len", AssistKind::Generate), |
@@ -89,13 +96,6 @@ fn get_impl_method( | |||
89 | ty.iterate_method_candidates(db, krate, &traits_in_scope, Some(fn_name), |_, func| Some(func)) | 96 | ty.iterate_method_candidates(db, krate, &traits_in_scope, Some(fn_name), |_, func| Some(func)) |
90 | } | 97 | } |
91 | 98 | ||
92 | fn get_text_range_of_len_function(ctx: &AssistContext, impl_: &ast::Impl) -> Option<TextRange> { | ||
93 | let db = ctx.sema.db; | ||
94 | let func = get_impl_method(ctx, impl_, &known::len)?; | ||
95 | let node = func.source(db)?; | ||
96 | Some(node.syntax().value.text_range()) | ||
97 | } | ||
98 | |||
99 | #[cfg(test)] | 99 | #[cfg(test)] |
100 | mod tests { | 100 | mod tests { |
101 | use crate::tests::{check_assist, check_assist_not_applicable}; | 101 | use crate::tests::{check_assist, check_assist_not_applicable}; |
@@ -158,6 +158,23 @@ impl MyStruct { | |||
158 | } | 158 | } |
159 | 159 | ||
160 | #[test] | 160 | #[test] |
161 | fn len_fn_different_return_type() { | ||
162 | cov_mark::check!(len_fn_different_return_type); | ||
163 | check_assist_not_applicable( | ||
164 | generate_is_empty_from_len, | ||
165 | r#" | ||
166 | struct MyStruct { data: Vec<String> } | ||
167 | |||
168 | impl MyStruct { | ||
169 | p$0ub fn len(&self) -> u32 { | ||
170 | self.data.len() | ||
171 | } | ||
172 | } | ||
173 | "#, | ||
174 | ); | ||
175 | } | ||
176 | |||
177 | #[test] | ||
161 | fn generate_is_empty() { | 178 | fn generate_is_empty() { |
162 | check_assist( | 179 | check_assist( |
163 | generate_is_empty_from_len, | 180 | generate_is_empty_from_len, |