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.traits_in_scope();
96 ty.iterate_method_candidates(db, krate, &traits_in_scope, Some(fn_name), |_, func| Some(func))
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 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,
166 struct MyStruct { data: Vec<String> }
169 p$0ub fn len(&self) -> u32 {
178 fn generate_is_empty() {
180 generate_is_empty_from_len,
182 struct MyStruct { data: Vec<String> }
185 p$0ub fn len(&self) -> usize {
191 struct MyStruct { data: Vec<String> }
194 pub fn len(&self) -> usize {
198 pub fn is_empty(&self) -> bool {
207 fn multiple_functions_in_impl() {
209 generate_is_empty_from_len,
211 struct MyStruct { data: Vec<String> }
214 pub fn new() -> Self {
218 p$0ub fn len(&self) -> usize {
222 pub fn work(&self) -> Option<usize> {
228 struct MyStruct { data: Vec<String> }
231 pub fn new() -> Self {
235 pub fn len(&self) -> usize {
239 pub fn is_empty(&self) -> bool {
243 pub fn work(&self) -> Option<usize> {
252 fn multiple_impls() {
253 check_assist_not_applicable(
254 generate_is_empty_from_len,
256 struct MyStruct { data: Vec<String> }
259 p$0ub fn len(&self) -> usize {
265 pub fn is_empty(&self) -> bool {