From e4756cb4f6e66097638b9d101589358976be2ba8 Mon Sep 17 00:00:00 2001 From: Chetan Khilosiya Date: Tue, 23 Feb 2021 00:17:48 +0530 Subject: 7526: Rename crate assists to ide_assists. --- crates/ide_assists/src/handlers/generate_setter.rs | 198 +++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 crates/ide_assists/src/handlers/generate_setter.rs (limited to 'crates/ide_assists/src/handlers/generate_setter.rs') diff --git a/crates/ide_assists/src/handlers/generate_setter.rs b/crates/ide_assists/src/handlers/generate_setter.rs new file mode 100644 index 000000000..288cf745d --- /dev/null +++ b/crates/ide_assists/src/handlers/generate_setter.rs @@ -0,0 +1,198 @@ +use stdx::{format_to, to_lower_snake_case}; +use syntax::ast::{self, AstNode, NameOwner, VisibilityOwner}; + +use crate::{ + utils::{find_impl_block_end, find_struct_impl, generate_impl_text}, + AssistContext, AssistId, AssistKind, Assists, GroupLabel, +}; + +// Assist: generate_setter +// +// Generate a setter method. +// +// ``` +// struct Person { +// nam$0e: String, +// } +// ``` +// -> +// ``` +// struct Person { +// name: String, +// } +// +// impl Person { +// /// Set the person's name. +// fn set_name(&mut self, name: String) { +// self.name = name; +// } +// } +// ``` +pub(crate) fn generate_setter(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { + let strukt = ctx.find_node_at_offset::()?; + let field = ctx.find_node_at_offset::()?; + + let strukt_name = strukt.name()?; + let field_name = field.name()?; + let field_ty = field.ty()?; + + // Return early if we've found an existing fn + let fn_name = to_lower_snake_case(&field_name.to_string()); + let impl_def = find_struct_impl( + &ctx, + &ast::Adt::Struct(strukt.clone()), + format!("set_{}", fn_name).as_str(), + )?; + + let target = field.syntax().text_range(); + acc.add_group( + &GroupLabel("Generate getter/setter".to_owned()), + AssistId("generate_setter", AssistKind::Generate), + "Generate a setter method", + target, + |builder| { + let mut buf = String::with_capacity(512); + + let fn_name_spaced = fn_name.replace('_', " "); + let strukt_name_spaced = + to_lower_snake_case(&strukt_name.to_string()).replace('_', " "); + + if impl_def.is_some() { + buf.push('\n'); + } + + let vis = strukt.visibility().map_or(String::new(), |v| format!("{} ", v)); + format_to!( + buf, + " /// Set the {}'s {}. + {}fn set_{}(&mut self, {}: {}) {{ + self.{} = {}; + }}", + strukt_name_spaced, + fn_name_spaced, + vis, + fn_name, + fn_name, + field_ty, + fn_name, + fn_name, + ); + + let start_offset = impl_def + .and_then(|impl_def| find_impl_block_end(impl_def, &mut buf)) + .unwrap_or_else(|| { + buf = generate_impl_text(&ast::Adt::Struct(strukt.clone()), &buf); + strukt.syntax().text_range().end() + }); + + builder.insert(start_offset, buf); + }, + ) +} + +#[cfg(test)] +mod tests { + use crate::tests::{check_assist, check_assist_not_applicable}; + + use super::*; + + fn check_not_applicable(ra_fixture: &str) { + check_assist_not_applicable(generate_setter, ra_fixture) + } + + #[test] + fn test_generate_setter_from_field() { + check_assist( + generate_setter, + r#" +struct Person { + dat$0a: T, +}"#, + r#" +struct Person { + data: T, +} + +impl Person { + /// Set the person's data. + fn set_data(&mut self, data: T) { + self.data = data; + } +}"#, + ); + } + + #[test] + fn test_generate_setter_already_implemented() { + check_not_applicable( + r#" +struct Person { + dat$0a: T, +} + +impl Person { + fn set_data(&mut self, data: T) { + self.data = data; + } +}"#, + ); + } + + #[test] + fn test_generate_setter_from_field_with_visibility_marker() { + check_assist( + generate_setter, + r#" +pub(crate) struct Person { + dat$0a: T, +}"#, + r#" +pub(crate) struct Person { + data: T, +} + +impl Person { + /// Set the person's data. + pub(crate) fn set_data(&mut self, data: T) { + self.data = data; + } +}"#, + ); + } + + #[test] + fn test_multiple_generate_setter() { + check_assist( + generate_setter, + r#" +struct Context { + data: T, + cou$0nt: usize, +} + +impl Context { + /// Set the context's data. + fn set_data(&mut self, data: T) { + self.data = data; + } +}"#, + r#" +struct Context { + data: T, + count: usize, +} + +impl Context { + /// Set the context's data. + fn set_data(&mut self, data: T) { + self.data = data; + } + + /// Set the context's count. + fn set_count(&mut self, count: usize) { + self.count = count; + } +}"#, + ); + } +} -- cgit v1.2.3