1 use hir::{known, HasSource, Name};
8 assist_context::{AssistContext, Assists},
12 // Assist: generate_is_empty_from_len
14 // Generates is_empty implementation from the len method.
17 // struct MyStruct { data: Vec<String> }
20 // p$0ub fn len(&self) -> usize {
27 // struct MyStruct { data: Vec<String> }
30 // pub fn len(&self) -> usize {
34 // pub fn is_empty(&self) -> bool {
39 pub(crate) fn generate_is_empty_from_len(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
40 let fn_node = ctx.find_node_at_offset::<ast::Fn>()?;
41 let fn_name = fn_node.name()?;
43 if fn_name.text() != "len" {
44 cov_mark::hit!(len_function_not_present);
48 if fn_node.param_list()?.params().next().is_some() {
49 cov_mark::hit!(len_function_with_parameters);
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);
60 if get_impl_method(ctx, &impl_, &known::is_empty).is_some() {
61 cov_mark::hit!(is_empty_already_implemented);
65 let node = len_fn.source(ctx.sema.db)?;
66 let range = node.syntax().value.text_range();
69 AssistId("generate_is_empty_from_len", AssistKind::Generate),
70 "Generate a is_empty impl from a len function",
75 pub fn is_empty(&self) -> bool {
79 builder.insert(range.end(), code)
88 ) -> Option<hir::Function> {
90 let impl_def: hir::Impl = ctx.sema.to_def(impl_)?;
92 let scope = ctx.sema.scope(impl_.syntax());
93 let krate = impl_def.module(db).krate();
94 let ty = impl_def.self_ty(db);
95 let traits_in_scope = scope.visible_traits();
96 ty.iterate_method_candidates(db, krate, &traits_in_scope, None, Some(fn_name), |_, func| {
103 use crate::tests::{check_assist, check_assist_not_applicable};
108 fn len_function_not_present() {
109 cov_mark::check!(len_function_not_present);
110 check_assist_not_applicable(
111 generate_is_empty_from_len,
113 struct MyStruct { data: Vec<String> }
116 p$0ub fn test(&self) -> usize {
125 fn len_function_with_parameters() {
126 cov_mark::check!(len_function_with_parameters);
127 check_assist_not_applicable(
128 generate_is_empty_from_len,
130 struct MyStruct { data: Vec<String> }
133 p$0ub fn len(&self, _i: bool) -> usize {
142 fn is_empty_already_implemented() {
143 cov_mark::check!(is_empty_already_implemented);
144 check_assist_not_applicable(
145 generate_is_empty_from_len,
147 struct MyStruct { data: Vec<String> }
150 p$0ub fn len(&self) -> usize {
154 pub fn is_empty(&self) -> bool {
163 fn len_fn_different_return_type() {
164 cov_mark::check!(len_fn_different_return_type);
165 check_assist_not_applicable(
166 generate_is_empty_from_len,
168 struct MyStruct { data: Vec<String> }
171 p$0ub fn len(&self) -> u32 {
180 fn generate_is_empty() {
182 generate_is_empty_from_len,
184 struct MyStruct { data: Vec<String> }
187 p$0ub fn len(&self) -> usize {
193 struct MyStruct { data: Vec<String> }
196 pub fn len(&self) -> usize {
200 pub fn is_empty(&self) -> bool {
209 fn multiple_functions_in_impl() {
211 generate_is_empty_from_len,
213 struct MyStruct { data: Vec<String> }
216 pub fn new() -> Self {
220 p$0ub fn len(&self) -> usize {
224 pub fn work(&self) -> Option<usize> {
230 struct MyStruct { data: Vec<String> }
233 pub fn new() -> Self {
237 pub fn len(&self) -> usize {
241 pub fn is_empty(&self) -> bool {
245 pub fn work(&self) -> Option<usize> {
254 fn multiple_impls() {
255 check_assist_not_applicable(
256 generate_is_empty_from_len,
258 struct MyStruct { data: Vec<String> }
261 p$0ub fn len(&self) -> usize {
267 pub fn is_empty(&self) -> bool {