diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-03-16 07:41:58 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2021-03-16 07:41:58 +0000 |
commit | 8b4075ff1c1dcc8e2501c3716ce637c886fc79d9 (patch) | |
tree | 61b194cfdb180c85ee7a9a45a27d5abf32109ea7 /crates | |
parent | 152f385055510c65bd94238878be23a258f5cc19 (diff) | |
parent | 847ec9e84049fb51b0d8d9b3e7b167764fb93d9d (diff) |
Merge #8040
8040: 7709: Added the check for return type of len function. r=Veykril a=chetankhilosiya
Co-authored-by: Chetan Khilosiya <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir/src/lib.rs | 5 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/generate_is_empty_from_len.rs | 35 |
2 files changed, 31 insertions, 9 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index c5161dadd..52939e990 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -52,6 +52,7 @@ use hir_ty::{ | |||
52 | autoderef, | 52 | autoderef, |
53 | display::{write_bounds_like_dyn_trait_with_prefix, HirDisplayError, HirFormatter}, | 53 | display::{write_bounds_like_dyn_trait_with_prefix, HirDisplayError, HirFormatter}, |
54 | method_resolution::{self, TyFingerprint}, | 54 | method_resolution::{self, TyFingerprint}, |
55 | primitive::UintTy, | ||
55 | to_assoc_type_id, | 56 | to_assoc_type_id, |
56 | traits::{FnTrait, Solution, SolutionVariables}, | 57 | traits::{FnTrait, Solution, SolutionVariables}, |
57 | AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate, | 58 | AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate, |
@@ -1631,6 +1632,10 @@ impl Type { | |||
1631 | matches!(self.ty.value.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..)) | 1632 | matches!(self.ty.value.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..)) |
1632 | } | 1633 | } |
1633 | 1634 | ||
1635 | pub fn is_usize(&self) -> bool { | ||
1636 | matches!(self.ty.value.interned(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize))) | ||
1637 | } | ||
1638 | |||
1634 | pub fn remove_ref(&self) -> Option<Type> { | 1639 | pub fn remove_ref(&self) -> Option<Type> { |
1635 | match &self.ty.value.interned(&Interner) { | 1640 | match &self.ty.value.interned(&Interner) { |
1636 | TyKind::Ref(.., ty) => Some(self.derived(ty.clone())), | 1641 | 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, |