Merge #7572
7572: Add `find_or_create_impl_block` to assist utils r=matklad a=yoshuawuyts This is another continuation of https://github.com/rust-analyzer/rust-analyzer/pull/7562, introducing a small util to either find an `impl` block, or create a new one if none exists. I copied this code from the `generate_new` assist into https://github.com/rust-analyzer/rust-analyzer/pull/7562, and this unifies both into a helper. It doesn't feel super polished in its current state, but my hope is that this is enough of a starting point that it can be expanded on later. For example something that would be useful would be a flag which either returns the index of the start of the block, or the end of the block. Anyway, I hope this is useful. Thanks! Co-authored-by: Yoshua Wuyts <yoshuawuyts@gmail.com>
This commit is contained in:
commit
80ab753d7e
@ -1,9 +1,12 @@
|
|||||||
use stdx::{format_to, to_lower_snake_case};
|
use stdx::{format_to, to_lower_snake_case};
|
||||||
|
use syntax::ast::VisibilityOwner;
|
||||||
use syntax::ast::{self, AstNode, NameOwner};
|
use syntax::ast::{self, AstNode, NameOwner};
|
||||||
use syntax::{ast::VisibilityOwner, T};
|
|
||||||
use test_utils::mark;
|
use test_utils::mark;
|
||||||
|
|
||||||
use crate::{utils::find_struct_impl, AssistContext, AssistId, AssistKind, Assists};
|
use crate::{
|
||||||
|
utils::{find_impl_block, find_struct_impl},
|
||||||
|
AssistContext, AssistId, AssistKind, Assists,
|
||||||
|
};
|
||||||
|
|
||||||
// Assist: generate_enum_match_method
|
// Assist: generate_enum_match_method
|
||||||
//
|
//
|
||||||
@ -63,7 +66,6 @@ pub(crate) fn generate_enum_match_method(acc: &mut Assists, ctx: &AssistContext)
|
|||||||
}
|
}
|
||||||
|
|
||||||
let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{} ", v));
|
let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{} ", v));
|
||||||
|
|
||||||
format_to!(
|
format_to!(
|
||||||
buf,
|
buf,
|
||||||
" /// Returns `true` if the {} is [`{}`].
|
" /// Returns `true` if the {} is [`{}`].
|
||||||
@ -78,17 +80,7 @@ pub(crate) fn generate_enum_match_method(acc: &mut Assists, ctx: &AssistContext)
|
|||||||
);
|
);
|
||||||
|
|
||||||
let start_offset = impl_def
|
let start_offset = impl_def
|
||||||
.and_then(|impl_def| {
|
.and_then(|impl_def| find_impl_block(impl_def, &mut buf))
|
||||||
buf.push('\n');
|
|
||||||
let start = impl_def
|
|
||||||
.syntax()
|
|
||||||
.descendants_with_tokens()
|
|
||||||
.find(|t| t.kind() == T!['{'])?
|
|
||||||
.text_range()
|
|
||||||
.end();
|
|
||||||
|
|
||||||
Some(start)
|
|
||||||
})
|
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
buf = generate_impl_text(&parent_enum, &buf);
|
buf = generate_impl_text(&parent_enum, &buf);
|
||||||
parent_enum.syntax().text_range().end()
|
parent_enum.syntax().text_range().end()
|
||||||
|
@ -2,10 +2,13 @@ use itertools::Itertools;
|
|||||||
use stdx::format_to;
|
use stdx::format_to;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, AstNode, GenericParamsOwner, NameOwner, StructKind, VisibilityOwner},
|
ast::{self, AstNode, GenericParamsOwner, NameOwner, StructKind, VisibilityOwner},
|
||||||
SmolStr, T,
|
SmolStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{utils::find_struct_impl, AssistContext, AssistId, AssistKind, Assists};
|
use crate::{
|
||||||
|
utils::{find_impl_block, find_struct_impl},
|
||||||
|
AssistContext, AssistId, AssistKind, Assists,
|
||||||
|
};
|
||||||
|
|
||||||
// Assist: generate_new
|
// Assist: generate_new
|
||||||
//
|
//
|
||||||
@ -58,17 +61,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
|
|||||||
format_to!(buf, " {}fn new({}) -> Self {{ Self {{ {} }} }}", vis, params, fields);
|
format_to!(buf, " {}fn new({}) -> Self {{ Self {{ {} }} }}", vis, params, fields);
|
||||||
|
|
||||||
let start_offset = impl_def
|
let start_offset = impl_def
|
||||||
.and_then(|impl_def| {
|
.and_then(|impl_def| find_impl_block(impl_def, &mut buf))
|
||||||
buf.push('\n');
|
|
||||||
let start = impl_def
|
|
||||||
.syntax()
|
|
||||||
.descendants_with_tokens()
|
|
||||||
.find(|t| t.kind() == T!['{'])?
|
|
||||||
.text_range()
|
|
||||||
.end();
|
|
||||||
|
|
||||||
Some(start)
|
|
||||||
})
|
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
buf = generate_impl_text(&strukt, &buf);
|
buf = generate_impl_text(&strukt, &buf);
|
||||||
strukt.syntax().text_range().end()
|
strukt.syntax().text_range().end()
|
||||||
@ -93,7 +86,7 @@ fn generate_impl_text(strukt: &ast::Struct, code: &str) -> String {
|
|||||||
if let Some(type_params) = &type_params {
|
if let Some(type_params) = &type_params {
|
||||||
format_to!(buf, "{}", type_params.syntax());
|
format_to!(buf, "{}", type_params.syntax());
|
||||||
}
|
}
|
||||||
buf.push_str(" ");
|
buf.push(' ');
|
||||||
buf.push_str(strukt.name().unwrap().text());
|
buf.push_str(strukt.name().unwrap().text());
|
||||||
if let Some(type_params) = type_params {
|
if let Some(type_params) = type_params {
|
||||||
let lifetime_params = type_params
|
let lifetime_params = type_params
|
||||||
|
@ -274,10 +274,11 @@ pub(crate) fn does_pat_match_variant(pat: &ast::Pat, var: &ast::Pat) -> bool {
|
|||||||
// Uses a syntax-driven approach to find any impl blocks for the struct that
|
// Uses a syntax-driven approach to find any impl blocks for the struct that
|
||||||
// exist within the module/file
|
// exist within the module/file
|
||||||
//
|
//
|
||||||
// Returns `None` if we've found an existing `new` fn
|
// Returns `None` if we've found an existing fn
|
||||||
//
|
//
|
||||||
// FIXME: change the new fn checking to a more semantic approach when that's more
|
// FIXME: change the new fn checking to a more semantic approach when that's more
|
||||||
// viable (e.g. we process proc macros, etc)
|
// viable (e.g. we process proc macros, etc)
|
||||||
|
// FIXME: this partially overlaps with `find_impl_block`
|
||||||
pub(crate) fn find_struct_impl(
|
pub(crate) fn find_struct_impl(
|
||||||
ctx: &AssistContext,
|
ctx: &AssistContext,
|
||||||
strukt: &ast::AdtDef,
|
strukt: &ast::AdtDef,
|
||||||
@ -338,3 +339,18 @@ fn has_fn(imp: &ast::Impl, rhs_name: &str) -> bool {
|
|||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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> {
|
||||||
|
buf.push('\n');
|
||||||
|
let start = impl_def
|
||||||
|
.syntax()
|
||||||
|
.descendants_with_tokens()
|
||||||
|
.find(|t| t.kind() == T!['{'])?
|
||||||
|
.text_range()
|
||||||
|
.end();
|
||||||
|
Some(start)
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user