Merge #7650
7650: Add `find_impl_block_end` assist helper r=Veykril a=yoshuawuyts Fixes #7605. This makes it so assists can use helpers to either append a method to the start or the end of an `impl` block. Thanks! @Veykril if this is merged, perhaps it could be good to update the gif in https://github.com/rust-analyzer/rust-analyzer/pull/7617#issuecomment-776622135 ? -- this should fix the ordering issue when generating multiple methods. Co-authored-by: Yoshua Wuyts <yoshuawuyts@gmail.com>
This commit is contained in:
commit
4d51b56444
@ -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)
|
||||
}
|
||||
}"#,
|
||||
);
|
||||
}
|
||||
|
@ -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<T: Clone> Context<T> {
|
||||
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
|
||||
}
|
||||
}"#,
|
||||
);
|
||||
}
|
||||
|
@ -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<T: Clone> Context<T> {
|
||||
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
|
||||
}
|
||||
}"#,
|
||||
);
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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<T: Clone> Person<T> {
|
||||
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;
|
||||
}
|
||||
}"#,
|
||||
);
|
||||
}
|
||||
|
@ -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<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
|
||||
|
Loading…
x
Reference in New Issue
Block a user