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> }
21 // p$0ub fn len(&self) -> usize {
28 // struct MyStruct { data: Vec<String> }
32 // pub fn len(&self) -> usize {
37 // pub fn is_empty(&self) -> bool {
42 pub(crate) fn generate_is_empty_from_len(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
43 let fn_node = ctx.find_node_at_offset::<ast::Fn>()?;
44 let fn_name = fn_node.name()?;
46 if fn_name.text() != "len" {
47 cov_mark::hit!(len_function_not_present);
51 if fn_node.param_list()?.params().next().is_some() {
52 cov_mark::hit!(len_function_with_parameters);
56 let impl_ = fn_node.syntax().ancestors().find_map(ast::Impl::cast)?;
57 let len_fn = get_impl_method(ctx, &impl_, &known::len)?;
58 if !len_fn.ret_type(ctx.sema.db).is_usize() {
59 cov_mark::hit!(len_fn_different_return_type);
63 if get_impl_method(ctx, &impl_, &known::is_empty).is_some() {
64 cov_mark::hit!(is_empty_already_implemented);
68 let node = len_fn.source(ctx.sema.db)?;
69 let range = node.syntax().value.text_range();
72 AssistId("generate_is_empty_from_len", AssistKind::Generate),
73 "Generate a is_empty impl from a len function",
79 pub fn is_empty(&self) -> bool {
83 builder.insert(range.end(), code)
89 ctx: &AssistContext<'_>,
92 ) -> Option<hir::Function> {
94 let impl_def: hir::Impl = ctx.sema.to_def(impl_)?;
96 let scope = ctx.sema.scope(impl_.syntax())?;
97 let ty = impl_def.self_ty(db);
98 ty.iterate_method_candidates(
101 &scope.visible_traits().0,
110 use crate::tests::{check_assist, check_assist_not_applicable};
115 fn len_function_not_present() {
116 cov_mark::check!(len_function_not_present);
117 check_assist_not_applicable(
118 generate_is_empty_from_len,
120 struct MyStruct { data: Vec<String> }
123 p$0ub fn test(&self) -> usize {
132 fn len_function_with_parameters() {
133 cov_mark::check!(len_function_with_parameters);
134 check_assist_not_applicable(
135 generate_is_empty_from_len,
137 struct MyStruct { data: Vec<String> }
141 p$0ub fn len(&self, _i: bool) -> usize {
150 fn is_empty_already_implemented() {
151 cov_mark::check!(is_empty_already_implemented);
152 check_assist_not_applicable(
153 generate_is_empty_from_len,
155 struct MyStruct { data: Vec<String> }
159 p$0ub fn len(&self) -> usize {
164 pub fn is_empty(&self) -> bool {
173 fn len_fn_different_return_type() {
174 cov_mark::check!(len_fn_different_return_type);
175 check_assist_not_applicable(
176 generate_is_empty_from_len,
178 struct MyStruct { data: Vec<String> }
182 p$0ub fn len(&self) -> u32 {
191 fn generate_is_empty() {
193 generate_is_empty_from_len,
195 struct MyStruct { data: Vec<String> }
199 p$0ub fn len(&self) -> usize {
205 struct MyStruct { data: Vec<String> }
209 pub fn len(&self) -> usize {
214 pub fn is_empty(&self) -> bool {
223 fn multiple_functions_in_impl() {
225 generate_is_empty_from_len,
227 struct MyStruct { data: Vec<String> }
231 pub fn new() -> Self {
236 p$0ub fn len(&self) -> usize {
240 pub fn work(&self) -> Option<usize> {
246 struct MyStruct { data: Vec<String> }
250 pub fn new() -> Self {
255 pub fn len(&self) -> usize {
260 pub fn is_empty(&self) -> bool {
264 pub fn work(&self) -> Option<usize> {
273 fn multiple_impls() {
274 check_assist_not_applicable(
275 generate_is_empty_from_len,
277 struct MyStruct { data: Vec<String> }
281 p$0ub fn len(&self) -> usize {
288 pub fn is_empty(&self) -> bool {