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,
};
);
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()
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)
+ }
}"#,
);
}
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,
};
);
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()
pub(crate) fn data(&self) -> &T {
&self.data
}
+}"#,
+ );
+ }
+
+ #[test]
+ fn test_multiple_generate_getter() {
+ check_assist(
+ generate_getter,
+ r#"
+struct Context<T: Clone> {
+ data: T,
+ cou$0nt: usize,
+}
+
+impl<T: Clone> Context<T> {
+ /// Get a reference to the context's data.
+ fn data(&self) -> &T {
+ &self.data
+ }
+}"#,
+ r#"
+struct Context<T: Clone> {
+ data: T,
+ count: usize,
+}
+
+impl<T: Clone> Context<T> {
+ /// 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
+ }
}"#,
);
}
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,
};
);
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()
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<T: Clone> {
+ data: T,
+ cou$0nt: usize,
+}
+
+impl<T: Clone> Context<T> {
+ /// Get a mutable reference to the context's data.
+ fn data_mut(&mut self) -> &mut T {
+ &mut self.data
+ }
+}"#,
+ r#"
+struct Context<T: Clone> {
+ data: T,
+ count: usize,
+}
+
+impl<T: Clone> Context<T> {
+ /// 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
+ }
}"#,
);
}
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,
};
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()
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,
};
);
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()
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<T: Clone> {
+ data: T,
+ cou$0nt: usize,
+}
+
+impl<T: Clone> Context<T> {
+ /// Set the context's data.
+ fn set_data(&mut self, data: T) {
+ self.data = data;
+ }
+}"#,
+ r#"
+struct Context<T: Clone> {
+ data: T,
+ count: usize,
+}
+
+impl<T: Clone> Context<T> {
+ /// 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;
+ }
}"#,
);
}
//
// 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,
/// 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<TextSize> {
+pub(crate) fn find_impl_block_start(impl_def: ast::Impl, buf: &mut String) -> Option<TextSize> {
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<TextSize> {
+ 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 { <code> }` including type and lifetime