Auto merge of #13399 - DropDemBits:assists-format-args-capture-pt2, r=Veykril
Migrate assists to format args captures, part 2 Continuation of #13379 Migrates: - `generate_constant` - `generate_default_from_enum_variant` - `generate_default_from_new` - `generate_delegate_methods` - `generate_deref` - `generate_documentation_template` - `generate_enum_is_method` - `generate_enum_projection_method` - `generate_from_impl_for_enum` - `generate_function` - `generate_getter` - `generate_impl` - `generate_new` - `generate_setter`
This commit is contained in:
commit
a2e4f783a2
|
@ -77,7 +77,7 @@ pub(crate) fn generate_constant(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
|
||||||
target_data_for_generate_constant(ctx, current_module, constant_module).unwrap_or_else(
|
target_data_for_generate_constant(ctx, current_module, constant_module).unwrap_or_else(
|
||||||
|| {
|
|| {
|
||||||
let indent = IndentLevel::from_node(statement.syntax());
|
let indent = IndentLevel::from_node(statement.syntax());
|
||||||
(statement.syntax().text_range().start(), indent, None, format!("\n{}", indent))
|
(statement.syntax().text_range().start(), indent, None, format!("\n{indent}"))
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ pub(crate) fn generate_constant(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
|
||||||
if let Some(file_id) = file_id {
|
if let Some(file_id) = file_id {
|
||||||
builder.edit_file(file_id);
|
builder.edit_file(file_id);
|
||||||
}
|
}
|
||||||
builder.insert(offset, format!("{}{}", text, post_string));
|
builder.insert(offset, format!("{text}{post_string}"));
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -103,13 +103,13 @@ fn get_text_for_generate_constant(
|
||||||
) -> Option<String> {
|
) -> Option<String> {
|
||||||
let constant_token = not_exist_name_ref.pop()?;
|
let constant_token = not_exist_name_ref.pop()?;
|
||||||
let vis = if not_exist_name_ref.len() == 0 && !outer_exists { "" } else { "\npub " };
|
let vis = if not_exist_name_ref.len() == 0 && !outer_exists { "" } else { "\npub " };
|
||||||
let mut text = format!("{}const {}: {} = $0;", vis, constant_token, type_name);
|
let mut text = format!("{vis}const {constant_token}: {type_name} = $0;");
|
||||||
while let Some(name_ref) = not_exist_name_ref.pop() {
|
while let Some(name_ref) = not_exist_name_ref.pop() {
|
||||||
let vis = if not_exist_name_ref.len() == 0 && !outer_exists { "" } else { "\npub " };
|
let vis = if not_exist_name_ref.len() == 0 && !outer_exists { "" } else { "\npub " };
|
||||||
text = text.replace("\n", "\n ");
|
text = text.replace("\n", "\n ");
|
||||||
text = format!("{}mod {} {{{}\n}}", vis, name_ref.to_string(), text);
|
text = format!("{vis}mod {name_ref} {{{text}\n}}");
|
||||||
}
|
}
|
||||||
Some(text.replace("\n", &format!("\n{}", indent)))
|
Some(text.replace("\n", &format!("\n{indent}")))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn target_data_for_generate_constant(
|
fn target_data_for_generate_constant(
|
||||||
|
@ -134,7 +134,7 @@ fn target_data_for_generate_constant(
|
||||||
.find(|it| it.kind() == SyntaxKind::WHITESPACE && it.to_string().contains("\n"))
|
.find(|it| it.kind() == SyntaxKind::WHITESPACE && it.to_string().contains("\n"))
|
||||||
.is_some();
|
.is_some();
|
||||||
let post_string =
|
let post_string =
|
||||||
if siblings_has_newline { format!("{}", indent) } else { format!("\n{}", indent) };
|
if siblings_has_newline { format!("{indent}") } else { format!("\n{indent}") };
|
||||||
Some((offset, indent + 1, Some(file_id), post_string))
|
Some((offset, indent + 1, Some(file_id), post_string))
|
||||||
}
|
}
|
||||||
_ => Some((TextSize::from(0), 0.into(), Some(file_id), "\n".into())),
|
_ => Some((TextSize::from(0), 0.into(), Some(file_id), "\n".into())),
|
||||||
|
|
|
@ -55,12 +55,11 @@ pub(crate) fn generate_default_from_enum_variant(
|
||||||
let buf = format!(
|
let buf = format!(
|
||||||
r#"
|
r#"
|
||||||
|
|
||||||
impl Default for {0} {{
|
impl Default for {enum_name} {{
|
||||||
fn default() -> Self {{
|
fn default() -> Self {{
|
||||||
Self::{1}
|
Self::{variant_name}
|
||||||
}}
|
}}
|
||||||
}}"#,
|
}}"#,
|
||||||
enum_name, variant_name
|
|
||||||
);
|
);
|
||||||
edit.insert(start_offset, buf);
|
edit.insert(start_offset, buf);
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use ide_db::famous_defs::FamousDefs;
|
use ide_db::famous_defs::FamousDefs;
|
||||||
use itertools::Itertools;
|
|
||||||
use stdx::format_to;
|
use stdx::format_to;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, HasGenericParams, HasName, HasTypeBounds, Impl},
|
ast::{self, make, HasGenericParams, HasName, Impl},
|
||||||
AstNode,
|
AstNode,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,45 +76,47 @@ pub(crate) fn generate_default_from_new(acc: &mut Assists, ctx: &AssistContext<'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: based on from utils::generate_impl_text_inner
|
||||||
fn generate_trait_impl_text_from_impl(impl_: &ast::Impl, trait_text: &str, code: &str) -> String {
|
fn generate_trait_impl_text_from_impl(impl_: &ast::Impl, trait_text: &str, code: &str) -> String {
|
||||||
let generic_params = impl_.generic_param_list();
|
let impl_ty = impl_.self_ty().unwrap();
|
||||||
|
let generic_params = impl_.generic_param_list().map(|generic_params| {
|
||||||
|
let lifetime_params =
|
||||||
|
generic_params.lifetime_params().map(ast::GenericParam::LifetimeParam);
|
||||||
|
let ty_or_const_params = generic_params.type_or_const_params().filter_map(|param| {
|
||||||
|
// remove defaults since they can't be specified in impls
|
||||||
|
match param {
|
||||||
|
ast::TypeOrConstParam::Type(param) => {
|
||||||
|
let param = param.clone_for_update();
|
||||||
|
param.remove_default();
|
||||||
|
Some(ast::GenericParam::TypeParam(param))
|
||||||
|
}
|
||||||
|
ast::TypeOrConstParam::Const(param) => {
|
||||||
|
let param = param.clone_for_update();
|
||||||
|
param.remove_default();
|
||||||
|
Some(ast::GenericParam::ConstParam(param))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
make::generic_param_list(itertools::chain(lifetime_params, ty_or_const_params))
|
||||||
|
});
|
||||||
|
|
||||||
let mut buf = String::with_capacity(code.len());
|
let mut buf = String::with_capacity(code.len());
|
||||||
buf.push_str("\n\n");
|
buf.push_str("\n\n");
|
||||||
|
|
||||||
|
// `impl{generic_params} {trait_text} for {impl_.self_ty()}`
|
||||||
buf.push_str("impl");
|
buf.push_str("impl");
|
||||||
|
|
||||||
if let Some(generic_params) = &generic_params {
|
if let Some(generic_params) = &generic_params {
|
||||||
let lifetimes = generic_params.lifetime_params().map(|lt| format!("{}", lt.syntax()));
|
format_to!(buf, "{generic_params}")
|
||||||
let toc_params = generic_params.type_or_const_params().map(|toc_param| match toc_param {
|
|
||||||
ast::TypeOrConstParam::Type(type_param) => {
|
|
||||||
let mut buf = String::new();
|
|
||||||
if let Some(it) = type_param.name() {
|
|
||||||
format_to!(buf, "{}", it.syntax());
|
|
||||||
}
|
|
||||||
if let Some(it) = type_param.colon_token() {
|
|
||||||
format_to!(buf, "{} ", it);
|
|
||||||
}
|
|
||||||
if let Some(it) = type_param.type_bound_list() {
|
|
||||||
format_to!(buf, "{}", it.syntax());
|
|
||||||
}
|
|
||||||
buf
|
|
||||||
}
|
|
||||||
ast::TypeOrConstParam::Const(const_param) => const_param.syntax().to_string(),
|
|
||||||
});
|
|
||||||
let generics = lifetimes.chain(toc_params).format(", ");
|
|
||||||
format_to!(buf, "<{}>", generics);
|
|
||||||
}
|
}
|
||||||
|
format_to!(buf, " {trait_text} for {impl_ty}");
|
||||||
buf.push(' ');
|
|
||||||
buf.push_str(trait_text);
|
|
||||||
buf.push_str(" for ");
|
|
||||||
buf.push_str(&impl_.self_ty().unwrap().syntax().text().to_string());
|
|
||||||
|
|
||||||
match impl_.where_clause() {
|
match impl_.where_clause() {
|
||||||
Some(where_clause) => {
|
Some(where_clause) => {
|
||||||
format_to!(buf, "\n{}\n{{\n{}\n}}", where_clause, code);
|
format_to!(buf, "\n{where_clause}\n{{\n{code}\n}}");
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
format_to!(buf, " {{\n{}\n}}", code);
|
format_to!(buf, " {{\n{code}\n}}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,14 +51,14 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
|
||||||
Some(field) => {
|
Some(field) => {
|
||||||
let field_name = field.name()?;
|
let field_name = field.name()?;
|
||||||
let field_ty = field.ty()?;
|
let field_ty = field.ty()?;
|
||||||
(format!("{}", field_name), field_ty, field.syntax().text_range())
|
(format!("{field_name}"), field_ty, field.syntax().text_range())
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let field = ctx.find_node_at_offset::<ast::TupleField>()?;
|
let field = ctx.find_node_at_offset::<ast::TupleField>()?;
|
||||||
let field_list = ctx.find_node_at_offset::<ast::TupleFieldList>()?;
|
let field_list = ctx.find_node_at_offset::<ast::TupleFieldList>()?;
|
||||||
let field_list_index = field_list.fields().position(|it| it == field)?;
|
let field_list_index = field_list.fields().position(|it| it == field)?;
|
||||||
let field_ty = field.ty()?;
|
let field_ty = field.ty()?;
|
||||||
(format!("{}", field_list_index), field_ty, field.syntax().text_range())
|
(format!("{field_list_index}"), field_ty, field.syntax().text_range())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -78,10 +78,12 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
|
||||||
let adt = ast::Adt::Struct(strukt.clone());
|
let adt = ast::Adt::Struct(strukt.clone());
|
||||||
let name = method.name(ctx.db()).to_string();
|
let name = method.name(ctx.db()).to_string();
|
||||||
let impl_def = find_struct_impl(ctx, &adt, &name).flatten();
|
let impl_def = find_struct_impl(ctx, &adt, &name).flatten();
|
||||||
|
let method_name = method.name(ctx.db());
|
||||||
|
|
||||||
acc.add_group(
|
acc.add_group(
|
||||||
&GroupLabel("Generate delegate methods…".to_owned()),
|
&GroupLabel("Generate delegate methods…".to_owned()),
|
||||||
AssistId("generate_delegate_methods", AssistKind::Generate),
|
AssistId("generate_delegate_methods", AssistKind::Generate),
|
||||||
format!("Generate delegate for `{}.{}()`", field_name, method.name(ctx.db())),
|
format!("Generate delegate for `{field_name}.{method_name}()`"),
|
||||||
target,
|
target,
|
||||||
|builder| {
|
|builder| {
|
||||||
// Create the function
|
// Create the function
|
||||||
|
@ -151,12 +153,12 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
|
||||||
Some(cap) => {
|
Some(cap) => {
|
||||||
let offset = strukt.syntax().text_range().end();
|
let offset = strukt.syntax().text_range().end();
|
||||||
let snippet = render_snippet(cap, impl_def.syntax(), cursor);
|
let snippet = render_snippet(cap, impl_def.syntax(), cursor);
|
||||||
let snippet = format!("\n\n{}", snippet);
|
let snippet = format!("\n\n{snippet}");
|
||||||
builder.insert_snippet(cap, offset, snippet);
|
builder.insert_snippet(cap, offset, snippet);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let offset = strukt.syntax().text_range().end();
|
let offset = strukt.syntax().text_range().end();
|
||||||
let snippet = format!("\n\n{}", impl_def.syntax());
|
let snippet = format!("\n\n{impl_def}");
|
||||||
builder.insert(offset, snippet);
|
builder.insert(offset, snippet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ fn generate_record_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
|
||||||
let target = field.syntax().text_range();
|
let target = field.syntax().text_range();
|
||||||
acc.add(
|
acc.add(
|
||||||
AssistId("generate_deref", AssistKind::Generate),
|
AssistId("generate_deref", AssistKind::Generate),
|
||||||
format!("Generate `{:?}` impl using `{}`", deref_type_to_generate, field_name),
|
format!("Generate `{deref_type_to_generate:?}` impl using `{field_name}`"),
|
||||||
target,
|
target,
|
||||||
|edit| {
|
|edit| {
|
||||||
generate_edit(
|
generate_edit(
|
||||||
|
@ -106,7 +106,7 @@ fn generate_tuple_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()
|
||||||
let target = field.syntax().text_range();
|
let target = field.syntax().text_range();
|
||||||
acc.add(
|
acc.add(
|
||||||
AssistId("generate_deref", AssistKind::Generate),
|
AssistId("generate_deref", AssistKind::Generate),
|
||||||
format!("Generate `{:?}` impl using `{}`", deref_type_to_generate, field.syntax()),
|
format!("Generate `{deref_type_to_generate:?}` impl using `{field}`"),
|
||||||
target,
|
target,
|
||||||
|edit| {
|
|edit| {
|
||||||
generate_edit(
|
generate_edit(
|
||||||
|
@ -132,18 +132,16 @@ fn generate_edit(
|
||||||
let start_offset = strukt.syntax().text_range().end();
|
let start_offset = strukt.syntax().text_range().end();
|
||||||
let impl_code = match deref_type {
|
let impl_code = match deref_type {
|
||||||
DerefType::Deref => format!(
|
DerefType::Deref => format!(
|
||||||
r#" type Target = {0};
|
r#" type Target = {field_type_syntax};
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {{
|
fn deref(&self) -> &Self::Target {{
|
||||||
&self.{1}
|
&self.{field_name}
|
||||||
}}"#,
|
}}"#,
|
||||||
field_type_syntax, field_name
|
|
||||||
),
|
),
|
||||||
DerefType::DerefMut => format!(
|
DerefType::DerefMut => format!(
|
||||||
r#" fn deref_mut(&mut self) -> &mut Self::Target {{
|
r#" fn deref_mut(&mut self) -> &mut Self::Target {{
|
||||||
&mut self.{}
|
&mut self.{field_name}
|
||||||
}}"#,
|
}}"#,
|
||||||
field_name
|
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
let strukt_adt = ast::Adt::Struct(strukt);
|
let strukt_adt = ast::Adt::Struct(strukt);
|
||||||
|
|
|
@ -139,40 +139,44 @@ fn make_example_for_fn(ast_func: &ast::Fn, ctx: &AssistContext<'_>) -> Option<St
|
||||||
|
|
||||||
let mut example = String::new();
|
let mut example = String::new();
|
||||||
|
|
||||||
|
let use_path = build_path(ast_func, ctx)?;
|
||||||
let is_unsafe = ast_func.unsafe_token().is_some();
|
let is_unsafe = ast_func.unsafe_token().is_some();
|
||||||
let param_list = ast_func.param_list()?;
|
let param_list = ast_func.param_list()?;
|
||||||
let ref_mut_params = ref_mut_params(¶m_list);
|
let ref_mut_params = ref_mut_params(¶m_list);
|
||||||
let self_name = self_name(ast_func);
|
let self_name = self_name(ast_func);
|
||||||
|
|
||||||
format_to!(example, "use {};\n\n", build_path(ast_func, ctx)?);
|
format_to!(example, "use {use_path};\n\n");
|
||||||
if let Some(self_name) = &self_name {
|
if let Some(self_name) = &self_name {
|
||||||
if let Some(mtbl) = is_ref_mut_self(ast_func) {
|
if let Some(mut_) = is_ref_mut_self(ast_func) {
|
||||||
let mtbl = if mtbl == true { " mut" } else { "" };
|
let mut_ = if mut_ == true { "mut " } else { "" };
|
||||||
format_to!(example, "let{} {} = ;\n", mtbl, self_name);
|
format_to!(example, "let {mut_}{self_name} = ;\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for param_name in &ref_mut_params {
|
for param_name in &ref_mut_params {
|
||||||
format_to!(example, "let mut {} = ;\n", param_name);
|
format_to!(example, "let mut {param_name} = ;\n");
|
||||||
}
|
}
|
||||||
// Call the function, check result
|
// Call the function, check result
|
||||||
let function_call = function_call(ast_func, ¶m_list, self_name.as_deref(), is_unsafe)?;
|
let function_call = function_call(ast_func, ¶m_list, self_name.as_deref(), is_unsafe)?;
|
||||||
if returns_a_value(ast_func, ctx) {
|
if returns_a_value(ast_func, ctx) {
|
||||||
if count_parameters(¶m_list) < 3 {
|
if count_parameters(¶m_list) < 3 {
|
||||||
format_to!(example, "assert_eq!({}, );\n", function_call);
|
format_to!(example, "assert_eq!({function_call}, );\n");
|
||||||
} else {
|
} else {
|
||||||
format_to!(example, "let result = {};\n", function_call);
|
format_to!(example, "let result = {function_call};\n");
|
||||||
example.push_str("assert_eq!(result, );\n");
|
example.push_str("assert_eq!(result, );\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
format_to!(example, "{};\n", function_call);
|
format_to!(example, "{function_call};\n");
|
||||||
}
|
}
|
||||||
// Check the mutated values
|
// Check the mutated values
|
||||||
if is_ref_mut_self(ast_func) == Some(true) {
|
if let Some(self_name) = &self_name {
|
||||||
format_to!(example, "assert_eq!({}, );", self_name?);
|
if is_ref_mut_self(ast_func) == Some(true) {
|
||||||
|
format_to!(example, "assert_eq!({self_name}, );");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for param_name in &ref_mut_params {
|
for param_name in &ref_mut_params {
|
||||||
format_to!(example, "assert_eq!({}, );", param_name);
|
format_to!(example, "assert_eq!({param_name}, );");
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(example)
|
Some(example)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +193,8 @@ fn introduction_builder(ast_func: &ast::Fn, ctx: &AssistContext<'_>) -> Option<S
|
||||||
let intro_for_new = || {
|
let intro_for_new = || {
|
||||||
let is_new = name == "new";
|
let is_new = name == "new";
|
||||||
if is_new && ret_ty == self_ty {
|
if is_new && ret_ty == self_ty {
|
||||||
Some(format!("Creates a new [`{}`].", linkable_self_ty?))
|
let self_ty = linkable_self_ty?;
|
||||||
|
Some(format!("Creates a new [`{self_ty}`]."))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -214,7 +219,9 @@ fn introduction_builder(ast_func: &ast::Fn, ctx: &AssistContext<'_>) -> Option<S
|
||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
Some(format!("Returns{reference} the {what} of this [`{}`].", linkable_self_ty?))
|
|
||||||
|
let self_ty = linkable_self_ty?;
|
||||||
|
Some(format!("Returns{reference} the {what} of this [`{self_ty}`]."))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
@ -228,7 +235,9 @@ fn introduction_builder(ast_func: &ast::Fn, ctx: &AssistContext<'_>) -> Option<S
|
||||||
if what == "len" {
|
if what == "len" {
|
||||||
what = "length".into()
|
what = "length".into()
|
||||||
};
|
};
|
||||||
Some(format!("Sets the {what} of this [`{}`].", linkable_self_ty?))
|
|
||||||
|
let self_ty = linkable_self_ty?;
|
||||||
|
Some(format!("Sets the {what} of this [`{self_ty}`]."))
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(intro) = intro_for_new() {
|
if let Some(intro) = intro_for_new() {
|
||||||
|
@ -404,7 +413,7 @@ fn arguments_from_params(param_list: &ast::ParamList) -> String {
|
||||||
// instance `TuplePat`) could be managed later.
|
// instance `TuplePat`) could be managed later.
|
||||||
Some(ast::Pat::IdentPat(ident_pat)) => match ident_pat.name() {
|
Some(ast::Pat::IdentPat(ident_pat)) => match ident_pat.name() {
|
||||||
Some(name) => match is_a_ref_mut_param(¶m) {
|
Some(name) => match is_a_ref_mut_param(¶m) {
|
||||||
true => format!("&mut {}", name),
|
true => format!("&mut {name}"),
|
||||||
false => name.to_string(),
|
false => name.to_string(),
|
||||||
},
|
},
|
||||||
None => "_".to_string(),
|
None => "_".to_string(),
|
||||||
|
@ -424,14 +433,15 @@ fn function_call(
|
||||||
let name = ast_func.name()?;
|
let name = ast_func.name()?;
|
||||||
let arguments = arguments_from_params(param_list);
|
let arguments = arguments_from_params(param_list);
|
||||||
let function_call = if param_list.self_param().is_some() {
|
let function_call = if param_list.self_param().is_some() {
|
||||||
format!("{}.{}({})", self_name?, name, arguments)
|
let self_ = self_name?;
|
||||||
|
format!("{self_}.{name}({arguments})")
|
||||||
} else if let Some(implementation) = self_partial_type(ast_func) {
|
} else if let Some(implementation) = self_partial_type(ast_func) {
|
||||||
format!("{}::{}({})", implementation, name, arguments)
|
format!("{implementation}::{name}({arguments})")
|
||||||
} else {
|
} else {
|
||||||
format!("{}({})", name, arguments)
|
format!("{name}({arguments})")
|
||||||
};
|
};
|
||||||
match is_unsafe {
|
match is_unsafe {
|
||||||
true => Some(format!("unsafe {{ {} }}", function_call)),
|
true => Some(format!("unsafe {{ {function_call} }}")),
|
||||||
false => Some(function_call),
|
false => Some(function_call),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -469,8 +479,8 @@ fn build_path(ast_func: &ast::Fn, ctx: &AssistContext<'_>) -> Option<String> {
|
||||||
.unwrap_or_else(|| "*".into());
|
.unwrap_or_else(|| "*".into());
|
||||||
let module_def: ModuleDef = ctx.sema.to_def(ast_func)?.module(ctx.db()).into();
|
let module_def: ModuleDef = ctx.sema.to_def(ast_func)?.module(ctx.db()).into();
|
||||||
match module_def.canonical_path(ctx.db()) {
|
match module_def.canonical_path(ctx.db()) {
|
||||||
Some(path) => Some(format!("{}::{}::{}", crate_name, path, leaf)),
|
Some(path) => Some(format!("{crate_name}::{path}::{leaf}")),
|
||||||
None => Some(format!("{}::{}", crate_name, leaf)),
|
None => Some(format!("{crate_name}::{leaf}")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,21 +61,15 @@ pub(crate) fn generate_enum_is_method(acc: &mut Assists, ctx: &AssistContext<'_>
|
||||||
"Generate an `is_` method for this enum variant",
|
"Generate an `is_` method for this enum variant",
|
||||||
target,
|
target,
|
||||||
|builder| {
|
|builder| {
|
||||||
let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{} ", v));
|
let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{v} "));
|
||||||
let method = format!(
|
let method = format!(
|
||||||
" /// Returns `true` if the {} is [`{variant}`].
|
" /// Returns `true` if the {enum_lowercase_name} is [`{variant_name}`].
|
||||||
///
|
///
|
||||||
/// [`{variant}`]: {}::{variant}
|
/// [`{variant_name}`]: {enum_name}::{variant_name}
|
||||||
#[must_use]
|
#[must_use]
|
||||||
{}fn {}(&self) -> bool {{
|
{vis}fn {fn_name}(&self) -> bool {{
|
||||||
matches!(self, Self::{variant}{})
|
matches!(self, Self::{variant_name}{pattern_suffix})
|
||||||
}}",
|
}}",
|
||||||
enum_lowercase_name,
|
|
||||||
enum_name,
|
|
||||||
vis,
|
|
||||||
fn_name,
|
|
||||||
pattern_suffix,
|
|
||||||
variant = variant_name
|
|
||||||
);
|
);
|
||||||
|
|
||||||
add_method_to_adt(builder, &parent_enum, impl_def, &method);
|
add_method_to_adt(builder, &parent_enum, impl_def, &method);
|
||||||
|
|
|
@ -116,6 +116,14 @@ fn generate_enum_projection_method(
|
||||||
assist_description: &str,
|
assist_description: &str,
|
||||||
props: ProjectionProps,
|
props: ProjectionProps,
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
|
let ProjectionProps {
|
||||||
|
fn_name_prefix,
|
||||||
|
self_param,
|
||||||
|
return_prefix,
|
||||||
|
return_suffix,
|
||||||
|
happy_case,
|
||||||
|
sad_case,
|
||||||
|
} = props;
|
||||||
let variant = ctx.find_node_at_offset::<ast::Variant>()?;
|
let variant = ctx.find_node_at_offset::<ast::Variant>()?;
|
||||||
let variant_name = variant.name()?;
|
let variant_name = variant.name()?;
|
||||||
let parent_enum = ast::Adt::Enum(variant.parent_enum());
|
let parent_enum = ast::Adt::Enum(variant.parent_enum());
|
||||||
|
@ -125,7 +133,7 @@ fn generate_enum_projection_method(
|
||||||
let (field,) = record.fields().collect_tuple()?;
|
let (field,) = record.fields().collect_tuple()?;
|
||||||
let name = field.name()?.to_string();
|
let name = field.name()?.to_string();
|
||||||
let ty = field.ty()?;
|
let ty = field.ty()?;
|
||||||
let pattern_suffix = format!(" {{ {} }}", name);
|
let pattern_suffix = format!(" {{ {name} }}");
|
||||||
(pattern_suffix, ty, name)
|
(pattern_suffix, ty, name)
|
||||||
}
|
}
|
||||||
ast::StructKind::Tuple(tuple) => {
|
ast::StructKind::Tuple(tuple) => {
|
||||||
|
@ -136,8 +144,7 @@ fn generate_enum_projection_method(
|
||||||
ast::StructKind::Unit => return None,
|
ast::StructKind::Unit => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let fn_name =
|
let fn_name = format!("{}_{}", fn_name_prefix, &to_lower_snake_case(&variant_name.text()));
|
||||||
format!("{}_{}", props.fn_name_prefix, &to_lower_snake_case(&variant_name.text()));
|
|
||||||
|
|
||||||
// Return early if we've found an existing new fn
|
// Return early if we've found an existing new fn
|
||||||
let impl_def = find_struct_impl(ctx, &parent_enum, &fn_name)?;
|
let impl_def = find_struct_impl(ctx, &parent_enum, &fn_name)?;
|
||||||
|
@ -149,27 +156,15 @@ fn generate_enum_projection_method(
|
||||||
assist_description,
|
assist_description,
|
||||||
target,
|
target,
|
||||||
|builder| {
|
|builder| {
|
||||||
let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{} ", v));
|
let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{v} "));
|
||||||
let method = format!(
|
let method = format!(
|
||||||
" {0}fn {1}({2}) -> {3}{4}{5} {{
|
" {vis}fn {fn_name}({self_param}) -> {return_prefix}{field_type}{return_suffix} {{
|
||||||
if let Self::{6}{7} = self {{
|
if let Self::{variant_name}{pattern_suffix} = self {{
|
||||||
{8}({9})
|
{happy_case}({bound_name})
|
||||||
}} else {{
|
}} else {{
|
||||||
{10}
|
{sad_case}
|
||||||
}}
|
}}
|
||||||
}}",
|
}}");
|
||||||
vis,
|
|
||||||
fn_name,
|
|
||||||
props.self_param,
|
|
||||||
props.return_prefix,
|
|
||||||
field_type.syntax(),
|
|
||||||
props.return_suffix,
|
|
||||||
variant_name,
|
|
||||||
pattern_suffix,
|
|
||||||
props.happy_case,
|
|
||||||
bound_name,
|
|
||||||
props.sad_case,
|
|
||||||
);
|
|
||||||
|
|
||||||
add_method_to_adt(builder, &parent_enum, impl_def, &method);
|
add_method_to_adt(builder, &parent_enum, impl_def, &method);
|
||||||
},
|
},
|
||||||
|
|
|
@ -56,23 +56,18 @@ pub(crate) fn generate_from_impl_for_enum(
|
||||||
target,
|
target,
|
||||||
|edit| {
|
|edit| {
|
||||||
let start_offset = variant.parent_enum().syntax().text_range().end();
|
let start_offset = variant.parent_enum().syntax().text_range().end();
|
||||||
let from_trait = format!("From<{}>", field_type.syntax());
|
let from_trait = format!("From<{field_type}>");
|
||||||
let impl_code = if let Some(name) = field_name {
|
let impl_code = if let Some(name) = field_name {
|
||||||
format!(
|
format!(
|
||||||
r#" fn from({0}: {1}) -> Self {{
|
r#" fn from({name}: {field_type}) -> Self {{
|
||||||
Self::{2} {{ {0} }}
|
Self::{variant_name} {{ {name} }}
|
||||||
}}"#,
|
}}"#
|
||||||
name.text(),
|
|
||||||
field_type.syntax(),
|
|
||||||
variant_name,
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
format!(
|
format!(
|
||||||
r#" fn from(v: {}) -> Self {{
|
r#" fn from(v: {field_type}) -> Self {{
|
||||||
Self::{}(v)
|
Self::{variant_name}(v)
|
||||||
}}"#,
|
}}"#
|
||||||
field_type.syntax(),
|
|
||||||
variant_name,
|
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
let from_impl = generate_trait_impl_text(&enum_, &from_trait, &impl_code);
|
let from_impl = generate_trait_impl_text(&enum_, &from_trait, &impl_code);
|
||||||
|
|
|
@ -179,7 +179,7 @@ fn add_func_to_accumulator(
|
||||||
let function_template = function_builder.render(adt_name.is_some());
|
let function_template = function_builder.render(adt_name.is_some());
|
||||||
let mut func = function_template.to_string(ctx.config.snippet_cap);
|
let mut func = function_template.to_string(ctx.config.snippet_cap);
|
||||||
if let Some(name) = adt_name {
|
if let Some(name) = adt_name {
|
||||||
func = format!("\n{}impl {} {{\n{}\n{}}}", indent, name, func, indent);
|
func = format!("\n{indent}impl {name} {{\n{func}\n{indent}}}");
|
||||||
}
|
}
|
||||||
builder.edit_file(file);
|
builder.edit_file(file);
|
||||||
match ctx.config.snippet_cap {
|
match ctx.config.snippet_cap {
|
||||||
|
@ -212,23 +212,26 @@ struct FunctionTemplate {
|
||||||
|
|
||||||
impl FunctionTemplate {
|
impl FunctionTemplate {
|
||||||
fn to_string(&self, cap: Option<SnippetCap>) -> String {
|
fn to_string(&self, cap: Option<SnippetCap>) -> String {
|
||||||
|
let Self { leading_ws, fn_def, ret_type, should_focus_return_type, trailing_ws, tail_expr } =
|
||||||
|
self;
|
||||||
|
|
||||||
let f = match cap {
|
let f = match cap {
|
||||||
Some(cap) => {
|
Some(cap) => {
|
||||||
let cursor = if self.should_focus_return_type {
|
let cursor = if *should_focus_return_type {
|
||||||
// Focus the return type if there is one
|
// Focus the return type if there is one
|
||||||
match self.ret_type {
|
match ret_type {
|
||||||
Some(ref ret_type) => ret_type.syntax(),
|
Some(ret_type) => ret_type.syntax(),
|
||||||
None => self.tail_expr.syntax(),
|
None => tail_expr.syntax(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.tail_expr.syntax()
|
tail_expr.syntax()
|
||||||
};
|
};
|
||||||
render_snippet(cap, self.fn_def.syntax(), Cursor::Replace(cursor))
|
render_snippet(cap, fn_def.syntax(), Cursor::Replace(cursor))
|
||||||
}
|
}
|
||||||
None => self.fn_def.to_string(),
|
None => fn_def.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
format!("{}{}{}", self.leading_ws, f, self.trailing_ws)
|
format!("{leading_ws}{f}{trailing_ws}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,9 +333,9 @@ impl FunctionBuilder {
|
||||||
let mut indent = IndentLevel::from_node(&it);
|
let mut indent = IndentLevel::from_node(&it);
|
||||||
if is_method {
|
if is_method {
|
||||||
indent = indent + 1;
|
indent = indent + 1;
|
||||||
leading_ws = format!("{}", indent);
|
leading_ws = format!("{indent}");
|
||||||
} else {
|
} else {
|
||||||
leading_ws = format!("\n\n{}", indent);
|
leading_ws = format!("\n\n{indent}");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn_def = fn_def.indent(indent);
|
fn_def = fn_def.indent(indent);
|
||||||
|
@ -340,9 +343,10 @@ impl FunctionBuilder {
|
||||||
}
|
}
|
||||||
GeneratedFunctionTarget::InEmptyItemList(it) => {
|
GeneratedFunctionTarget::InEmptyItemList(it) => {
|
||||||
let indent = IndentLevel::from_node(&it);
|
let indent = IndentLevel::from_node(&it);
|
||||||
leading_ws = format!("\n{}", indent + 1);
|
let leading_indent = indent + 1;
|
||||||
fn_def = fn_def.indent(indent + 1);
|
leading_ws = format!("\n{leading_indent}");
|
||||||
trailing_ws = format!("\n{}", indent);
|
fn_def = fn_def.indent(leading_indent);
|
||||||
|
trailing_ws = format!("\n{indent}");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -108,9 +108,9 @@ pub(crate) fn generate_getter_impl(
|
||||||
buf.push('\n');
|
buf.push('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
let vis = strukt.visibility().map_or(String::new(), |v| format!("{} ", v));
|
let vis = strukt.visibility().map_or(String::new(), |v| format!("{v} "));
|
||||||
let (ty, body) = if mutable {
|
let (ty, body) = if mutable {
|
||||||
(format!("&mut {}", field_ty), format!("&mut self.{}", field_name))
|
(format!("&mut {field_ty}"), format!("&mut self.{field_name}"))
|
||||||
} else {
|
} else {
|
||||||
(|| {
|
(|| {
|
||||||
let krate = ctx.sema.scope(field_ty.syntax())?.krate();
|
let krate = ctx.sema.scope(field_ty.syntax())?.krate();
|
||||||
|
@ -126,19 +126,15 @@ pub(crate) fn generate_getter_impl(
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})()
|
})()
|
||||||
.unwrap_or_else(|| (format!("&{}", field_ty), format!("&self.{}", field_name)))
|
.unwrap_or_else(|| (format!("&{field_ty}"), format!("&self.{field_name}")))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut_ = mutable.then(|| "mut ").unwrap_or_default();
|
||||||
format_to!(
|
format_to!(
|
||||||
buf,
|
buf,
|
||||||
" {}fn {}(&{}self) -> {} {{
|
" {vis}fn {fn_name}(&{mut_}self) -> {ty} {{
|
||||||
{}
|
{body}
|
||||||
}}",
|
}}"
|
||||||
vis,
|
|
||||||
fn_name,
|
|
||||||
mutable.then(|| "mut ").unwrap_or_default(),
|
|
||||||
ty,
|
|
||||||
body,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let start_offset = impl_def
|
let start_offset = impl_def
|
||||||
|
|
|
@ -28,7 +28,7 @@ pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
|
||||||
|
|
||||||
acc.add(
|
acc.add(
|
||||||
AssistId("generate_impl", AssistKind::Generate),
|
AssistId("generate_impl", AssistKind::Generate),
|
||||||
format!("Generate impl for `{}`", name),
|
format!("Generate impl for `{name}`"),
|
||||||
target,
|
target,
|
||||||
|edit| {
|
|edit| {
|
||||||
let start_offset = nominal.syntax().text_range().end();
|
let start_offset = nominal.syntax().text_range().end();
|
||||||
|
|
|
@ -51,11 +51,13 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
|
||||||
buf.push('\n');
|
buf.push('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
let vis = strukt.visibility().map_or(String::new(), |v| format!("{} ", v));
|
let vis = strukt.visibility().map_or(String::new(), |v| format!("{v} "));
|
||||||
|
|
||||||
let trivial_constructors = field_list
|
let trivial_constructors = field_list
|
||||||
.fields()
|
.fields()
|
||||||
.map(|f| {
|
.map(|f| {
|
||||||
|
let name = f.name()?;
|
||||||
|
|
||||||
let ty = ctx.sema.resolve_type(&f.ty()?)?;
|
let ty = ctx.sema.resolve_type(&f.ty()?)?;
|
||||||
|
|
||||||
let item_in_ns = hir::ItemInNs::from(hir::ModuleDef::from(ty.as_adt()?));
|
let item_in_ns = hir::ItemInNs::from(hir::ModuleDef::from(ty.as_adt()?));
|
||||||
|
@ -72,7 +74,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
|
||||||
&ty,
|
&ty,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Some(format!("{}: {}", f.name()?.syntax(), expr))
|
Some(format!("{name}: {expr}"))
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
@ -81,7 +83,10 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter_map(|(i, f)| {
|
.filter_map(|(i, f)| {
|
||||||
if trivial_constructors[i].is_none() {
|
if trivial_constructors[i].is_none() {
|
||||||
Some(format!("{}: {}", f.name()?.syntax(), f.ty()?.syntax()))
|
let name = f.name()?;
|
||||||
|
let ty = f.ty()?;
|
||||||
|
|
||||||
|
Some(format!("{name}: {ty}"))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -101,7 +106,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
|
||||||
})
|
})
|
||||||
.format(", ");
|
.format(", ");
|
||||||
|
|
||||||
format_to!(buf, " {}fn new({}) -> Self {{ Self {{ {} }} }}", vis, params, fields);
|
format_to!(buf, " {vis}fn new({params}) -> Self {{ Self {{ {fields} }} }}");
|
||||||
|
|
||||||
let start_offset = impl_def
|
let start_offset = impl_def
|
||||||
.and_then(|impl_def| find_impl_block_start(impl_def, &mut buf))
|
.and_then(|impl_def| find_impl_block_start(impl_def, &mut buf))
|
||||||
|
|
|
@ -39,7 +39,7 @@ pub(crate) fn generate_setter(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt
|
||||||
let impl_def = find_struct_impl(
|
let impl_def = find_struct_impl(
|
||||||
ctx,
|
ctx,
|
||||||
&ast::Adt::Struct(strukt.clone()),
|
&ast::Adt::Struct(strukt.clone()),
|
||||||
format!("set_{}", fn_name).as_str(),
|
format!("set_{fn_name}").as_str(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let target = field.syntax().text_range();
|
let target = field.syntax().text_range();
|
||||||
|
@ -55,18 +55,12 @@ pub(crate) fn generate_setter(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt
|
||||||
buf.push('\n');
|
buf.push('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
let vis = strukt.visibility().map_or(String::new(), |v| format!("{} ", v));
|
let vis = strukt.visibility().map_or(String::new(), |v| format!("{v} "));
|
||||||
format_to!(
|
format_to!(
|
||||||
buf,
|
buf,
|
||||||
" {}fn set_{}(&mut self, {}: {}) {{
|
" {vis}fn set_{fn_name}(&mut self, {fn_name}: {field_ty}) {{
|
||||||
self.{} = {};
|
self.{fn_name} = {fn_name};
|
||||||
}}",
|
}}"
|
||||||
vis,
|
|
||||||
fn_name,
|
|
||||||
fn_name,
|
|
||||||
field_ty,
|
|
||||||
fn_name,
|
|
||||||
fn_name,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let start_offset = impl_def
|
let start_offset = impl_def
|
||||||
|
|
Loading…
Reference in a new issue