1 use hir::{AssocItem, HasSource, Impl};
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.
18 // p$0ub fn len(&self) -> usize {
26 // pub fn len(&self) -> usize {
30 // pub fn is_empty(&self) -> bool {
35 pub(crate) fn generate_is_empty_from_len(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
36 let fn_node = ctx.find_node_at_offset::<ast::Fn>()?;
37 let fn_name = fn_node.name()?;
39 if fn_name.text() != "len" {
40 cov_mark::hit!(len_function_not_present);
44 if fn_node.param_list()?.params().next().is_some() {
45 cov_mark::hit!(len_function_with_parameters);
49 let impl_ = fn_node.syntax().ancestors().into_iter().find_map(ast::Impl::cast)?;
50 let impl_def = ctx.sema.to_def(&impl_)?;
51 if is_empty_implemented(ctx, &impl_def) {
52 cov_mark::hit!(is_empty_already_implemented);
56 let range = get_text_range_of_len_function(ctx, &impl_def)?;
59 AssistId("generate_is_empty_from_len", AssistKind::Generate),
60 "Generate a is_empty impl from a len function",
63 let code = get_is_empty_code();
64 builder.insert(range.end(), code)
69 fn get_function_from_impl(ctx: &AssistContext, impl_def: &Impl, name: &str) -> Option<AssocItem> {
71 impl_def.items(db).into_iter().filter(|item| matches!(item, AssocItem::Function(_value))).find(
72 |func| match func.name(db) {
73 Some(fn_name) => fn_name.to_string() == name,
79 fn is_empty_implemented(ctx: &AssistContext, impl_def: &Impl) -> bool {
80 get_function_from_impl(ctx, impl_def, "is_empty").is_some()
83 fn get_text_range_of_len_function(ctx: &AssistContext, impl_def: &Impl) -> Option<TextRange> {
85 let len_fn = get_function_from_impl(ctx, impl_def, "len")?;
88 if let AssocItem::Function(node) = len_fn {
89 let node = node.source(db)?;
90 range = Some(node.syntax().value.text_range());
96 fn get_is_empty_code() -> String {
99 pub fn is_empty(&self) -> bool {
107 use crate::tests::{check_assist, check_assist_not_applicable};
112 fn len_function_not_present() {
113 cov_mark::check!(len_function_not_present);
114 check_assist_not_applicable(
115 generate_is_empty_from_len,
118 p$0ub fn test(&self) -> usize {
127 fn len_function_with_parameters() {
128 cov_mark::check!(len_function_with_parameters);
129 check_assist_not_applicable(
130 generate_is_empty_from_len,
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,
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,
166 p$0ub fn len(&self) -> usize {
173 pub fn len(&self) -> usize {
177 pub fn is_empty(&self) -> bool {
186 fn multiple_functions_in_impl() {
188 generate_is_empty_from_len,
191 pub fn new() -> Self {
195 p$0ub fn len(&self) -> usize {
199 pub fn work(&self) -> Option<usize> {
206 pub fn new() -> Self {
210 pub fn len(&self) -> usize {
214 pub fn is_empty(&self) -> bool {
218 pub fn work(&self) -> Option<usize> {