From ac959b82b3408fafd22f4fbb59e10383a18c545f Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Fri, 12 Feb 2021 11:48:43 +0100 Subject: Add `find_impl_block_end` assist helper --- .../src/handlers/generate_enum_match_method.rs | 41 ++++++++++++++++++++-- crates/assists/src/handlers/generate_getter.rs | 40 +++++++++++++++++++-- crates/assists/src/handlers/generate_getter_mut.rs | 40 +++++++++++++++++++-- crates/assists/src/handlers/generate_new.rs | 4 +-- crates/assists/src/handlers/generate_setter.rs | 40 +++++++++++++++++++-- crates/assists/src/utils.rs | 24 ++++++++----- 6 files changed, 171 insertions(+), 18 deletions(-) diff --git a/crates/assists/src/handlers/generate_enum_match_method.rs b/crates/assists/src/handlers/generate_enum_match_method.rs index c3ff38b66..aeb887e71 100644 --- a/crates/assists/src/handlers/generate_enum_match_method.rs +++ b/crates/assists/src/handlers/generate_enum_match_method.rs @@ -4,7 +4,7 @@ use syntax::ast::{self, AstNode, NameOwner}; use test_utils::mark; use crate::{ - utils::{find_impl_block, find_struct_impl, generate_impl_text}, + utils::{find_impl_block_end, find_struct_impl, generate_impl_text}, AssistContext, AssistId, AssistKind, Assists, }; @@ -80,7 +80,7 @@ pub(crate) fn generate_enum_match_method(acc: &mut Assists, ctx: &AssistContext) ); let start_offset = impl_def - .and_then(|impl_def| find_impl_block(impl_def, &mut buf)) + .and_then(|impl_def| find_impl_block_end(impl_def, &mut buf)) .unwrap_or_else(|| { buf = generate_impl_text(&ast::Adt::Enum(parent_enum.clone()), &buf); parent_enum.syntax().text_range().end() @@ -197,6 +197,43 @@ impl Variant { pub(crate) fn is_minor(&self) -> bool { matches!(self, Self::Minor) } +}"#, + ); + } + + #[test] + fn test_multiple_generate_enum_match_from_variant() { + check_assist( + generate_enum_match_method, + r#" +enum Variant { + Undefined, + Minor, + Major$0, +} + +impl Variant { + /// Returns `true` if the variant is [`Minor`]. + fn is_minor(&self) -> bool { + matches!(self, Self::Minor) + } +}"#, + r#"enum Variant { + Undefined, + Minor, + Major, +} + +impl Variant { + /// Returns `true` if the variant is [`Minor`]. + fn is_minor(&self) -> bool { + matches!(self, Self::Minor) + } + + /// Returns `true` if the variant is [`Major`]. + fn is_major(&self) -> bool { + matches!(self, Self::Major) + } }"#, ); } diff --git a/crates/assists/src/handlers/generate_getter.rs b/crates/assists/src/handlers/generate_getter.rs index b63dfce41..fbcf8b069 100644 --- a/crates/assists/src/handlers/generate_getter.rs +++ b/crates/assists/src/handlers/generate_getter.rs @@ -3,7 +3,7 @@ use syntax::ast::VisibilityOwner; use syntax::ast::{self, AstNode, NameOwner}; use crate::{ - utils::{find_impl_block, find_struct_impl, generate_impl_text}, + utils::{find_impl_block_end, find_struct_impl, generate_impl_text}, AssistContext, AssistId, AssistKind, Assists, }; @@ -73,7 +73,7 @@ pub(crate) fn generate_getter(acc: &mut Assists, ctx: &AssistContext) -> Option< ); let start_offset = impl_def - .and_then(|impl_def| find_impl_block(impl_def, &mut buf)) + .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() @@ -150,6 +150,42 @@ impl Context { pub(crate) fn data(&self) -> &T { &self.data } +}"#, + ); + } + + #[test] + fn test_multiple_generate_getter() { + check_assist( + generate_getter, + r#" +struct Context { + data: T, + cou$0nt: usize, +} + +impl Context { + /// Get a reference to the context's data. + fn data(&self) -> &T { + &self.data + } +}"#, + r#" +struct Context { + data: T, + count: usize, +} + +impl Context { + /// Get a reference to the context's data. + fn data(&self) -> &T { + &self.data + } + + /// Get a reference to the context's count. + fn count(&self) -> &usize { + &self.count + } }"#, ); } diff --git a/crates/assists/src/handlers/generate_getter_mut.rs b/crates/assists/src/handlers/generate_getter_mut.rs index b5085035e..bf0d99881 100644 --- a/crates/assists/src/handlers/generate_getter_mut.rs +++ b/crates/assists/src/handlers/generate_getter_mut.rs @@ -3,7 +3,7 @@ use syntax::ast::VisibilityOwner; use syntax::ast::{self, AstNode, NameOwner}; use crate::{ - utils::{find_impl_block, find_struct_impl, generate_impl_text}, + utils::{find_impl_block_end, find_struct_impl, generate_impl_text}, AssistContext, AssistId, AssistKind, Assists, }; @@ -76,7 +76,7 @@ pub(crate) fn generate_getter_mut(acc: &mut Assists, ctx: &AssistContext) -> Opt ); let start_offset = impl_def - .and_then(|impl_def| find_impl_block(impl_def, &mut buf)) + .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() @@ -153,6 +153,42 @@ impl Context { pub(crate) fn data_mut(&mut self) -> &mut T { &mut self.data } +}"#, + ); + } + + #[test] + fn test_multiple_generate_getter_mut() { + check_assist( + generate_getter_mut, + r#" +struct Context { + data: T, + cou$0nt: usize, +} + +impl Context { + /// Get a mutable reference to the context's data. + fn data_mut(&mut self) -> &mut T { + &mut self.data + } +}"#, + r#" +struct Context { + data: T, + count: usize, +} + +impl Context { + /// Get a mutable reference to the context's data. + fn data_mut(&mut self) -> &mut T { + &mut self.data + } + + /// Get a mutable reference to the context's count. + fn count_mut(&mut self) -> &mut usize { + &mut self.count + } }"#, ); } diff --git a/crates/assists/src/handlers/generate_new.rs b/crates/assists/src/handlers/generate_new.rs index c29077225..8ce5930b7 100644 --- a/crates/assists/src/handlers/generate_new.rs +++ b/crates/assists/src/handlers/generate_new.rs @@ -4,7 +4,7 @@ use stdx::format_to; use syntax::ast::{self, AstNode, NameOwner, StructKind, VisibilityOwner}; use crate::{ - utils::{find_impl_block, find_struct_impl, generate_impl_text}, + utils::{find_impl_block_start, find_struct_impl, generate_impl_text}, AssistContext, AssistId, AssistKind, Assists, }; @@ -58,7 +58,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()> format_to!(buf, " {}fn new({}) -> Self {{ Self {{ {} }} }}", vis, params, fields); let start_offset = impl_def - .and_then(|impl_def| find_impl_block(impl_def, &mut buf)) + .and_then(|impl_def| find_impl_block_start(impl_def, &mut buf)) .unwrap_or_else(|| { buf = generate_impl_text(&Adt::Struct(strukt.clone()), &buf); strukt.syntax().text_range().end() diff --git a/crates/assists/src/handlers/generate_setter.rs b/crates/assists/src/handlers/generate_setter.rs index c9043a162..b655f9b9c 100644 --- a/crates/assists/src/handlers/generate_setter.rs +++ b/crates/assists/src/handlers/generate_setter.rs @@ -3,7 +3,7 @@ use syntax::ast::VisibilityOwner; use syntax::ast::{self, AstNode, NameOwner}; use crate::{ - utils::{find_impl_block, find_struct_impl, generate_impl_text}, + utils::{find_impl_block_end, find_struct_impl, generate_impl_text}, AssistContext, AssistId, AssistKind, Assists, }; @@ -79,7 +79,7 @@ pub(crate) fn generate_setter(acc: &mut Assists, ctx: &AssistContext) -> Option< ); let start_offset = impl_def - .and_then(|impl_def| find_impl_block(impl_def, &mut buf)) + .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() @@ -156,6 +156,42 @@ impl Person { 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; + } }"#, ); } diff --git a/crates/assists/src/utils.rs b/crates/assists/src/utils.rs index 643dade23..5dd32aef1 100644 --- a/crates/assists/src/utils.rs +++ b/crates/assists/src/utils.rs @@ -279,7 +279,7 @@ pub(crate) fn does_pat_match_variant(pat: &ast::Pat, var: &ast::Pat) -> bool { // // FIXME: change the new fn checking to a more semantic approach when that's more // viable (e.g. we process proc macros, etc) -// FIXME: this partially overlaps with `find_impl_block` +// FIXME: this partially overlaps with `find_impl_block_*` pub(crate) fn find_struct_impl( ctx: &AssistContext, strukt: &ast::Adt, @@ -343,17 +343,25 @@ fn has_fn(imp: &ast::Impl, rhs_name: &str) -> bool { /// Find the start of the `impl` block for the given `ast::Impl`. // -// FIXME: add a way to find the end of the `impl` block. // FIXME: this partially overlaps with `find_struct_impl` -pub(crate) fn find_impl_block(impl_def: ast::Impl, buf: &mut String) -> Option { +pub(crate) fn find_impl_block_start(impl_def: ast::Impl, buf: &mut String) -> Option { buf.push('\n'); - let start = impl_def - .syntax() - .descendants_with_tokens() - .find(|t| t.kind() == T!['{'])? + let start = impl_def.assoc_item_list().and_then(|it| it.l_curly_token())?.text_range().end(); + Some(start) +} + +/// Find the end of the `impl` block for the given `ast::Impl`. +// +// FIXME: this partially overlaps with `find_struct_impl` +pub(crate) fn find_impl_block_end(impl_def: ast::Impl, buf: &mut String) -> Option { + buf.push('\n'); + let end = impl_def + .assoc_item_list() + .and_then(|it| it.r_curly_token())? + .prev_sibling_or_token()? .text_range() .end(); - Some(start) + Some(end) } // Generates the surrounding `impl Type { }` including type and lifetime -- cgit v1.2.3