aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-03-16 07:41:58 +0000
committerGitHub <[email protected]>2021-03-16 07:41:58 +0000
commit8b4075ff1c1dcc8e2501c3716ce637c886fc79d9 (patch)
tree61b194cfdb180c85ee7a9a45a27d5abf32109ea7 /crates
parent152f385055510c65bd94238878be23a258f5cc19 (diff)
parent847ec9e84049fb51b0d8d9b3e7b167764fb93d9d (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.rs5
-rw-r--r--crates/ide_assists/src/handlers/generate_is_empty_from_len.rs35
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 @@
1use hir::{known, HasSource, Name}; 1use hir::{known, HasSource, Name};
2use syntax::{ 2use syntax::{
3 ast::{self, NameOwner}, 3 ast::{self, NameOwner},
4 AstNode, TextRange, 4 AstNode,
5}; 5};
6 6
7use crate::{ 7use 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
92fn 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)]
100mod tests { 100mod 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#"
166struct MyStruct { data: Vec<String> }
167
168impl 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,