Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/ide-assists/src/handlers/add_missing_match_arms.rs14
-rw-r--r--crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs17
-rw-r--r--crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs19
-rw-r--r--crates/ide-assists/src/handlers/generate_trait_from_impl.rs22
-rw-r--r--crates/ide-assists/src/handlers/remove_dbg.rs28
-rw-r--r--crates/ide-assists/src/handlers/unmerge_imports.rs13
-rw-r--r--crates/ide-assists/src/handlers/unwrap_block.rs10
-rw-r--r--crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs49
8 files changed, 91 insertions, 81 deletions
diff --git a/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/crates/ide-assists/src/handlers/add_missing_match_arms.rs
index 9f267daa10..3c33ddec31 100644
--- a/crates/ide-assists/src/handlers/add_missing_match_arms.rs
+++ b/crates/ide-assists/src/handlers/add_missing_match_arms.rs
@@ -8,7 +8,7 @@ use ide_db::{famous_defs::FamousDefs, helpers::mod_path_to_ast};
use itertools::Itertools;
use syntax::ast::edit::IndentLevel;
use syntax::ast::syntax_factory::SyntaxFactory;
-use syntax::ast::{self, AstNode, MatchArmList, MatchExpr, Pat, make};
+use syntax::ast::{self, AstNode, MatchArmList, MatchExpr, Pat};
use syntax::syntax_editor::{Position, SyntaxEditor};
use syntax::{SyntaxKind, SyntaxNode, ToSmolStr};
@@ -592,12 +592,12 @@ fn build_pat(
ExtendedVariant::Variant { variant: var, use_self } => {
let edition = module.krate(db).edition(db);
let path = if use_self {
- make::path_from_segments(
+ make.path_from_segments(
[
- make::path_segment(make::name_ref_self_ty()),
- make::path_segment(make::name_ref(
- &var.name(db).display(db, edition).to_smolstr(),
- )),
+ make.path_segment(make.name_ref_self_ty()),
+ make.path_segment(
+ make.name_ref(&var.name(db).display(db, edition).to_smolstr()),
+ ),
],
false,
)
@@ -611,7 +611,7 @@ fn build_pat(
let pats = fields.into_iter().map(|f| {
let name = name_generator.for_type(&f.ty(db).to_type(db), db, edition);
match name {
- Some(name) => make::ext::simple_ident_pat(make.name(&name)).into(),
+ Some(name) => make.ident_pat(false, false, make.name(&name)).into(),
None => make.wildcard_pat().into(),
}
});
diff --git a/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs b/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs
index 21404564fa..5b691dba5e 100644
--- a/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs
+++ b/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs
@@ -99,21 +99,20 @@ fn edit_struct_def(
) {
// Note that we don't need to consider macro files in this function because this is
// currently not triggered for struct definitions inside macro calls.
+ let editor = builder.make_editor(strukt.syntax());
+ let make = editor.make();
+
let tuple_fields = record_fields.fields().filter_map(|f| {
- let (editor, field) =
- SyntaxEditor::with_ast_node(&ast::make::tuple_field(f.visibility(), f.ty()?));
- editor.insert_all(
+ let (field_editor, field) =
+ SyntaxEditor::with_ast_node(&make.tuple_field(f.visibility(), f.ty()?));
+ field_editor.insert_all(
Position::first_child_of(field.syntax()),
f.attrs().map(|attr| attr.syntax().clone().into()).collect(),
);
- let field_syntax = editor.finish().new_root().clone();
- let field = ast::TupleField::cast(field_syntax)?;
- Some(field)
+ let field_syntax = field_editor.finish().new_root().clone();
+ ast::TupleField::cast(field_syntax)
});
- let editor = builder.make_editor(strukt.syntax());
- let make = editor.make();
-
let tuple_fields = make.tuple_field_list(tuple_fields);
let mut elements = vec![tuple_fields.syntax().clone().into()];
diff --git a/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs b/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
index a1b33a0558..afbcf024b9 100644
--- a/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
+++ b/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
@@ -105,7 +105,7 @@ fn edit_struct_def(
let make = editor.make();
let record_fields = tuple_fields.fields().zip(names).filter_map(|(f, name)| {
let (field_editor, field) =
- SyntaxEditor::with_ast_node(&ast::make::record_field(f.visibility(), name, f.ty()?));
+ SyntaxEditor::with_ast_node(&make.record_field(f.visibility(), name, f.ty()?));
field_editor.insert_all(
Position::first_child_of(field.syntax()),
f.attrs().map(|attr| attr.syntax().clone().into()).collect(),
@@ -119,21 +119,21 @@ fn edit_struct_def(
if let Some(w) = strukt.where_clause() {
editor.delete(w.syntax());
let mut insert_element = Vec::new();
- insert_element.push(ast::make::tokens::single_newline().syntax_element());
+ insert_element.push(make.whitespace("\n").syntax_element());
insert_element.push(w.syntax().syntax_element());
if w.syntax().last_token().is_none_or(|t| t.kind() != SyntaxKind::COMMA) {
- insert_element.push(ast::make::token(T![,]).into());
+ insert_element.push(make.token(T![,]).into());
}
- insert_element.push(ast::make::tokens::single_newline().syntax_element());
+ insert_element.push(make.whitespace("\n").syntax_element());
editor.insert_all(tuple_fields_before, insert_element);
} else {
- editor.insert(tuple_fields_before, ast::make::tokens::single_space());
+ editor.insert(tuple_fields_before, make.whitespace(" "));
}
if let Some(t) = strukt.semicolon_token() {
editor.delete(t);
}
} else {
- editor.insert(tuple_fields_before, ast::make::tokens::single_space());
+ editor.insert(tuple_fields_before, make.whitespace(" "));
}
editor.replace(tuple_fields.syntax(), record_fields.syntax());
@@ -189,7 +189,7 @@ fn process_struct_name_reference(
let range = ctx.sema.original_range_opt(tuple_struct_pat.syntax())?.range;
let new = make.record_pat_with_fields(
full_path,
- generate_record_pat_list(&tuple_struct_pat, names),
+ generate_record_pat_list(&tuple_struct_pat, names, make),
);
editor.replace_all(cover_edit_range(source.syntax(), range), vec![new.syntax().clone().into()]);
},
@@ -316,6 +316,7 @@ fn generate_names(
fn generate_record_pat_list(
pat: &ast::TupleStructPat,
names: &[ast::Name],
+ make: &SyntaxFactory,
) -> ast::RecordPatFieldList {
let pure_fields = pat.fields().filter(|p| !matches!(p, ast::Pat::RestPat(_)));
let rest_len = names.len().saturating_sub(pure_fields.clone().count());
@@ -327,8 +328,8 @@ fn generate_record_pat_list(
let fields = before_rest
.chain(after_rest)
- .map(|(pat, name)| ast::make::record_pat_field(ast::make::name_ref(&name.text()), pat));
- ast::make::record_pat_field_list(fields, rest_pat)
+ .map(|(pat, name)| make.record_pat_field(make.name_ref(&name.text()), pat));
+ make.record_pat_field_list(fields, rest_pat)
}
#[cfg(test)]
diff --git a/crates/ide-assists/src/handlers/generate_trait_from_impl.rs b/crates/ide-assists/src/handlers/generate_trait_from_impl.rs
index f5342b8b70..049398de8c 100644
--- a/crates/ide-assists/src/handlers/generate_trait_from_impl.rs
+++ b/crates/ide-assists/src/handlers/generate_trait_from_impl.rs
@@ -3,7 +3,8 @@ use ide_db::assists::AssistId;
use syntax::{
AstNode, AstToken, SyntaxKind, T,
ast::{
- self, HasDocComments, HasGenericParams, HasName, HasVisibility, edit::AstNodeEdit, make,
+ self, HasDocComments, HasGenericParams, HasName, HasVisibility, edit::AstNodeEdit,
+ syntax_factory::SyntaxFactory,
},
syntax_editor::{Position, SyntaxEditor},
};
@@ -112,7 +113,7 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
let make = editor.make();
let trait_ast = make.trait_(
false,
- &trait_name(&impl_assoc_items).text(),
+ &trait_name(&impl_assoc_items, make).text(),
impl_ast.generic_param_list(),
impl_ast.where_clause(),
trait_items,
@@ -124,9 +125,9 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
// Change `impl Foo` to `impl NewTrait for Foo`
let mut elements = vec![
trait_name_ref.syntax().clone().into(),
- make::tokens::single_space().into(),
- make::token(T![for]).into(),
- make::tokens::single_space().into(),
+ make.whitespace(" ").into(),
+ make.token(T![for]).into(),
+ make.whitespace(" ").into(),
];
if let Some(params) = impl_ast.generic_param_list() {
@@ -146,7 +147,7 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
Position::before(impl_ast.syntax()),
vec![
trait_ast.syntax().clone().into(),
- make::tokens::whitespace(&format!("\n\n{}", impl_ast.indent_level())).into(),
+ make.whitespace(&format!("\n\n{}", impl_ast.indent_level())).into(),
],
);
@@ -163,16 +164,16 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
Some(())
}
-fn trait_name(items: &ast::AssocItemList) -> ast::Name {
+fn trait_name(items: &ast::AssocItemList, make: &SyntaxFactory) -> ast::Name {
let mut fn_names = items
.assoc_items()
.filter_map(|x| if let ast::AssocItem::Fn(f) = x { f.name() } else { None });
fn_names
.next()
.and_then(|name| {
- fn_names.next().is_none().then(|| make::name(&stdx::to_camel_case(&name.text())))
+ fn_names.next().is_none().then(|| make.name(&stdx::to_camel_case(&name.text())))
})
- .unwrap_or_else(|| make::name("NewTrait"))
+ .unwrap_or_else(|| make.name("NewTrait"))
}
/// `E0449` Trait items always share the visibility of their trait
@@ -202,6 +203,7 @@ fn remove_doc_comments(editor: &SyntaxEditor, item: &ast::AssocItem) {
}
fn strip_body(editor: &SyntaxEditor, item: &ast::AssocItem) {
+ let make = editor.make();
if let ast::AssocItem::Fn(f) = item
&& let Some(body) = f.body()
{
@@ -213,7 +215,7 @@ fn strip_body(editor: &SyntaxEditor, item: &ast::AssocItem) {
editor.delete(prev);
}
- editor.replace(body.syntax(), make::tokens::semicolon());
+ editor.replace(body.syntax(), make.token(T![;]));
};
}
diff --git a/crates/ide-assists/src/handlers/remove_dbg.rs b/crates/ide-assists/src/handlers/remove_dbg.rs
index 32fae8a5bb..778533be5a 100644
--- a/crates/ide-assists/src/handlers/remove_dbg.rs
+++ b/crates/ide-assists/src/handlers/remove_dbg.rs
@@ -1,7 +1,7 @@
use itertools::Itertools;
use syntax::{
Edition, NodeOrToken, SyntaxNode, SyntaxToken, T,
- ast::{self, AstNode, make},
+ ast::{self, AstNode, syntax_factory::SyntaxFactory},
match_ast,
syntax_editor::{Position, SyntaxEditor},
};
@@ -24,6 +24,8 @@ use crate::{AssistContext, AssistId, Assists};
// }
// ```
pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
+ let (editor, _) = SyntaxEditor::new(ctx.source_file().syntax().clone());
+ let make = editor.make();
let macro_calls = if ctx.has_empty_selection() {
vec![ctx.find_node_at_offset::<ast::MacroExpr>()?]
} else {
@@ -39,15 +41,16 @@ pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
.collect()
};
- let replacements =
- macro_calls.into_iter().filter_map(compute_dbg_replacement).collect::<Vec<_>>();
+ let replacements = macro_calls
+ .into_iter()
+ .filter_map(|macro_expr| compute_dbg_replacement(macro_expr, make))
+ .collect::<Vec<_>>();
let target = replacements
.iter()
.flat_map(|(node_or_token, _)| node_or_token.iter())
.map(|t| t.text_range())
.reduce(|acc, range| acc.cover(range))?;
acc.add(AssistId::quick_fix("remove_dbg"), "Remove dbg!()", target, |builder| {
- let editor = builder.make_editor(ctx.source_file().syntax());
for (range, expr) in replacements {
if let Some(expr) = expr {
editor.insert(Position::before(range[0].clone()), expr.syntax());
@@ -68,6 +71,7 @@ pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
/// Returns `Some(_, None)` when the macro call should just be removed.
fn compute_dbg_replacement(
macro_expr: ast::MacroExpr,
+ make: &SyntaxFactory,
) -> Option<(Vec<NodeOrToken<SyntaxNode, SyntaxToken>>, Option<ast::Expr>)> {
let macro_call = macro_expr.macro_call()?;
let tt = macro_call.token_tree()?;
@@ -110,7 +114,7 @@ fn compute_dbg_replacement(
}
(replace, None)
},
- _ => (vec![macro_call.syntax().clone().into()], Some(make::ext::expr_unit())),
+ _ => (vec![macro_call.syntax().clone().into()], Some(make.expr_unit())),
}
}
}
@@ -162,14 +166,14 @@ fn compute_dbg_replacement(
},
None => false,
};
- let expr = replace_nested_dbgs(expr.clone());
- let expr = if wrap { make::expr_paren(expr).into() } else { expr };
+ let expr = replace_nested_dbgs(expr.clone(), make);
+ let expr = if wrap { make.expr_paren(expr).into() } else { expr };
(vec![macro_call.syntax().clone().into()], Some(expr))
}
// dbg!(expr0, expr1, ...)
exprs => {
- let exprs = exprs.iter().cloned().map(replace_nested_dbgs);
- let expr = make::expr_tuple(exprs);
+ let exprs = exprs.iter().cloned().map(|expr| replace_nested_dbgs(expr, make));
+ let expr = make.expr_tuple(exprs);
(vec![macro_call.syntax().clone().into()], Some(expr.into()))
}
})
@@ -189,12 +193,12 @@ fn pure_expr(expr: &ast::Expr) -> bool {
}
}
-fn replace_nested_dbgs(expanded: ast::Expr) -> ast::Expr {
+fn replace_nested_dbgs(expanded: ast::Expr, make: &SyntaxFactory) -> ast::Expr {
if let ast::Expr::MacroExpr(mac) = &expanded {
// Special-case when `expanded` itself is `dbg!()` since we cannot replace the whole tree
// with `ted`. It should be fairly rare as it means the user wrote `dbg!(dbg!(..))` but you
// never know how code ends up being!
- let replaced = if let Some((_, expr_opt)) = compute_dbg_replacement(mac.clone()) {
+ let replaced = if let Some((_, expr_opt)) = compute_dbg_replacement(mac.clone(), make) {
match expr_opt {
Some(expr) => expr,
None => {
@@ -215,7 +219,7 @@ fn replace_nested_dbgs(expanded: ast::Expr) -> ast::Expr {
expanded.syntax().descendants().filter_map(ast::MacroExpr::cast).collect();
for mac in macro_exprs {
- let expr_opt = match compute_dbg_replacement(mac.clone()) {
+ let expr_opt = match compute_dbg_replacement(mac.clone(), make) {
Some((_, expr)) => expr,
None => continue,
};
diff --git a/crates/ide-assists/src/handlers/unmerge_imports.rs b/crates/ide-assists/src/handlers/unmerge_imports.rs
index 8875a72246..ab6317ad44 100644
--- a/crates/ide-assists/src/handlers/unmerge_imports.rs
+++ b/crates/ide-assists/src/handlers/unmerge_imports.rs
@@ -1,7 +1,7 @@
use syntax::{
AstNode, SyntaxKind,
- ast::{self, HasAttrs, HasVisibility, edit::IndentLevel, make},
- syntax_editor::{Element, Position, Removable},
+ ast::{self, HasAttrs, HasVisibility, edit::IndentLevel, syntax_factory::SyntaxFactory},
+ syntax_editor::{Element, Position, Removable, SyntaxEditor},
};
use crate::{
@@ -22,6 +22,8 @@ use crate::{
// use std::fmt::Display;
// ```
pub(crate) fn unmerge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
+ let (editor, _) = SyntaxEditor::new(ctx.source_file().syntax().clone());
+ let make = editor.make();
let tree = ctx.find_node_at_offset::<ast::UseTree>()?;
let tree_list = tree.syntax().parent().and_then(ast::UseTreeList::cast)?;
@@ -31,7 +33,7 @@ pub(crate) fn unmerge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt
}
let use_ = tree_list.syntax().ancestors().find_map(ast::Use::cast)?;
- let path = resolve_full_path(&tree)?;
+ let path = resolve_full_path(&tree, make)?;
// If possible, explain what is going to be done.
let label = match tree.path().and_then(|path| path.first_segment()) {
@@ -41,7 +43,6 @@ pub(crate) fn unmerge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt
let target = tree.syntax().text_range();
acc.add(AssistId::refactor_rewrite("unmerge_imports"), label, target, |builder| {
- let editor = builder.make_editor(use_.syntax());
let make = editor.make();
let new_use = make.use_(
use_.attrs(),
@@ -64,7 +65,7 @@ pub(crate) fn unmerge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt
})
}
-fn resolve_full_path(tree: &ast::UseTree) -> Option<ast::Path> {
+fn resolve_full_path(tree: &ast::UseTree, make: &SyntaxFactory) -> Option<ast::Path> {
let paths = tree
.syntax()
.ancestors()
@@ -72,7 +73,7 @@ fn resolve_full_path(tree: &ast::UseTree) -> Option<ast::Path> {
.filter_map(ast::UseTree::cast)
.filter_map(|t| t.path());
- let final_path = paths.reduce(|prev, next| make::path_concat(next, prev))?;
+ let final_path = paths.reduce(|prev, next| make.path_concat(next, prev))?;
if final_path.segment().is_some_and(|it| it.self_token().is_some()) {
final_path.qualifier()
} else {
diff --git a/crates/ide-assists/src/handlers/unwrap_block.rs b/crates/ide-assists/src/handlers/unwrap_block.rs
index 23bbe21437..77941bcfb2 100644
--- a/crates/ide-assists/src/handlers/unwrap_block.rs
+++ b/crates/ide-assists/src/handlers/unwrap_block.rs
@@ -3,7 +3,6 @@ use syntax::{
ast::{
self,
edit::{AstNodeEdit, IndentLevel},
- make,
},
match_ast,
syntax_editor::{Element, Position, SyntaxEditor},
@@ -83,7 +82,8 @@ pub(crate) fn unwrap_block(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
})
}
-fn delete_else_before(container: SyntaxNode, edit: &SyntaxEditor) {
+fn delete_else_before(container: SyntaxNode, editor: &SyntaxEditor) {
+ let make = editor.make();
let Some(else_token) = container
.siblings_with_tokens(syntax::Direction::Prev)
.skip(1)
@@ -94,10 +94,10 @@ fn delete_else_before(container: SyntaxNode, edit: &SyntaxEditor) {
};
itertools::chain(else_token.prev_token(), else_token.next_token())
.filter(|it| it.kind() == SyntaxKind::WHITESPACE)
- .for_each(|it| edit.delete(it));
+ .for_each(|it| editor.delete(it));
let indent = IndentLevel::from_node(&container);
- let newline = make::tokens::whitespace(&format!("\n{indent}"));
- edit.replace(else_token, newline);
+ let newline = make.whitespace(&format!("\n{indent}"));
+ editor.replace(else_token, newline);
}
fn wrap_let(assign: &ast::LetStmt, replacement: ast::BlockExpr) -> ast::BlockExpr {
diff --git a/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs b/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs
index f40769e0d7..635fab857d 100644
--- a/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs
+++ b/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs
@@ -1,8 +1,7 @@
use ide_db::source_change::SourceChangeBuilder;
-use itertools::Itertools;
use syntax::{
NodeOrToken, SyntaxToken, T, TextRange, algo,
- ast::{self, AstNode, edit::AstNodeEdit, make},
+ ast::{self, AstNode, edit::AstNodeEdit},
};
use crate::{AssistContext, AssistId, Assists};
@@ -151,7 +150,7 @@ pub(crate) fn wrap_unwrap_cfg_attr(acc: &mut Assists, ctx: &AssistContext<'_>) -
if let [attr] = &attrs[..]
&& let Some(ast::Meta::CfgAttrMeta(meta)) = attr.meta()
{
- unwrap_cfg_attr(acc, meta)
+ unwrap_cfg_attr(acc, ctx, meta)
} else {
wrap_cfg_attrs(acc, ctx, attrs)
}
@@ -267,37 +266,41 @@ fn wrap_cfg_attrs(acc: &mut Assists, ctx: &AssistContext<'_>, attrs: Vec<ast::At
Some(())
}
-fn unwrap_cfg_attr(acc: &mut Assists, meta: ast::CfgAttrMeta) -> Option<()> {
+fn unwrap_cfg_attr(
+ acc: &mut Assists,
+ ctx: &AssistContext<'_>,
+ meta: ast::CfgAttrMeta,
+) -> Option<()> {
let top_attr = ast::Meta::from(meta.clone()).parent_attr()?;
let range = top_attr.syntax().text_range();
- let inner_attrs = meta
- .metas()
- .map(|meta| {
- if top_attr.excl_token().is_some() {
- make::attr_inner(meta)
- } else {
- make::attr_outer(meta)
- }
- })
- .collect::<Vec<_>>();
- if inner_attrs.is_empty() {
+ let inner_metas: Vec<ast::Meta> = meta.metas().collect();
+ if inner_metas.is_empty() {
return None;
}
- let handle_source_change = |f: &mut SourceChangeBuilder| {
- let inner_attrs = inner_attrs
- .iter()
- .map(|it| it.to_string())
- .join(&format!("\n{}", top_attr.indent_level()));
- f.replace(range, inner_attrs);
- };
+ let is_inner = top_attr.excl_token().is_some();
+ let indent = top_attr.indent_level();
acc.add(
AssistId::refactor("wrap_unwrap_cfg_attr"),
"Extract Inner Attributes from `cfg_attr`",
range,
- handle_source_change,
+ |builder: &mut SourceChangeBuilder| {
+ let editor = builder.make_editor(top_attr.syntax());
+ let make = editor.make();
+ let mut elements = vec![];
+ for (i, meta) in inner_metas.into_iter().enumerate() {
+ if i > 0 {
+ elements.push(make.whitespace(&format!("\n{indent}")).into());
+ }
+ let attr = if is_inner { make.attr_inner(meta) } else { make.attr_outer(meta) };
+ elements.push(attr.syntax().clone().into());
+ }
+ editor.replace_with_many(top_attr.syntax(), elements);
+ builder.add_file_edits(ctx.vfs_file_id(), editor);
+ },
);
Some(())
}
+
#[cfg(test)]
mod tests {
use crate::tests::check_assist;