1 use hir::{known, HasSource, Name};
3 ast::{self, NameOwner},
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 if get_impl_method(ctx, &impl_, &known::is_empty).is_some() {
55 cov_mark::hit!(is_empty_already_implemented);
59 let range = get_text_range_of_len_function(ctx, &impl_)?;
62 AssistId("generate_is_empty_from_len", AssistKind::Generate),
63 "Generate a is_empty impl from a len function",
68 pub fn is_empty(&self) -> bool {
72 builder.insert(range.end(), code)
81 ) -> Option<hir::Function> {
83 let impl_def: hir::Impl = ctx.sema.to_def(impl_)?;
85 let scope = ctx.sema.scope(impl_.syntax());
86 let krate = impl_def.module(db).krate();
87 let ty = impl_def.target_ty(db);
88 let traits_in_scope = scope.traits_in_scope();
89 ty.iterate_method_candidates(db, krate, &traits_in_scope, Some(fn_name), |_, func| Some(func))
92 fn get_text_range_of_len_function(ctx: &AssistContext, impl_: &ast::Impl) -> Option<TextRange> {
94 let func = get_impl_method(ctx, impl_, &known::len)?;
95 let node = func.source(db)?;
96 Some(node.syntax().value.text_range())
101 use crate::tests::{check_assist, check_assist_not_applicable};
106 fn len_function_not_present() {
107 cov_mark::check!(len_function_not_present);
108 check_assist_not_applicable(
109 generate_is_empty_from_len,
111 struct MyStruct { data: Vec<String> }
114 p$0ub fn test(&self) -> usize {
123 fn len_function_with_parameters() {
124 cov_mark::check!(len_function_with_parameters);
125 check_assist_not_applicable(
126 generate_is_empty_from_len,
128 struct MyStruct { data: Vec<String> }
131 p$0ub fn len(&self, _i: bool) -> usize {
140 fn is_empty_already_implemented() {
141 cov_mark::check!(is_empty_already_implemented);
142 check_assist_not_applicable(
143 generate_is_empty_from_len,
145 struct MyStruct { data: Vec<String> }
148 p$0ub fn len(&self) -> usize {
152 pub fn is_empty(&self) -> bool {
161 fn generate_is_empty() {
163 generate_is_empty_from_len,
165 struct MyStruct { data: Vec<String> }
168 p$0ub fn len(&self) -> usize {
174 struct MyStruct { data: Vec<String> }
177 pub fn len(&self) -> usize {
181 pub fn is_empty(&self) -> bool {
190 fn multiple_functions_in_impl() {
192 generate_is_empty_from_len,
194 struct MyStruct { data: Vec<String> }
197 pub fn new() -> Self {
201 p$0ub fn len(&self) -> usize {
205 pub fn work(&self) -> Option<usize> {
211 struct MyStruct { data: Vec<String> }
214 pub fn new() -> Self {
218 pub fn len(&self) -> usize {
222 pub fn is_empty(&self) -> bool {
226 pub fn work(&self) -> Option<usize> {
235 fn multiple_impls() {
236 check_assist_not_applicable(
237 generate_is_empty_from_len,
239 struct MyStruct { data: Vec<String> }
242 p$0ub fn len(&self) -> usize {
248 pub fn is_empty(&self) -> bool {