Skip to content

Commit d70e67b

Browse files
committed
Migrate PathTransform to SyntaxEditor
Signed-off-by: Hayashi Mikihiro <[email protected]>
1 parent 9e9ff76 commit d70e67b

File tree

8 files changed

+168
-86
lines changed

8 files changed

+168
-86
lines changed

src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ use syntax::{
1616
SyntaxKind::*,
1717
SyntaxNode, T,
1818
ast::{
19-
self, AstNode, HasAttrs, HasGenericParams, HasName, HasVisibility, edit::IndentLevel,
20-
edit_in_place::Indent, make,
19+
self, AstNode, HasAttrs, HasGenericParams, HasName, HasVisibility,
20+
edit::{AstNodeEdit, IndentLevel},
21+
make,
2122
},
2223
match_ast, ted,
2324
};
@@ -110,20 +111,30 @@ pub(crate) fn extract_struct_from_enum_variant(
110111
let generics = generic_params.as_ref().map(|generics| generics.clone_for_update());
111112

112113
// resolve GenericArg in field_list to actual type
113-
let field_list = field_list.clone_for_update();
114-
if let Some((target_scope, source_scope)) =
114+
let field_list = if let Some((target_scope, source_scope)) =
115115
ctx.sema.scope(enum_ast.syntax()).zip(ctx.sema.scope(field_list.syntax()))
116116
{
117-
PathTransform::generic_transformation(&target_scope, &source_scope)
118-
.apply(field_list.syntax());
119-
}
117+
let field_list = field_list.reset_indent();
118+
let field_list =
119+
PathTransform::generic_transformation(&target_scope, &source_scope)
120+
.apply(field_list.syntax());
121+
match_ast! {
122+
match field_list {
123+
ast::RecordFieldList(field_list) => Either::Left(field_list),
124+
ast::TupleFieldList(field_list) => Either::Right(field_list),
125+
_ => unreachable!(),
126+
}
127+
}
128+
} else {
129+
field_list.clone_for_update()
130+
};
120131

121132
let def =
122133
create_struct_def(variant_name.clone(), &variant, &field_list, generics, &enum_ast);
123134

124135
let enum_ast = variant.parent_enum();
125136
let indent = enum_ast.indent_level();
126-
def.reindent_to(indent);
137+
let def = def.indent(indent);
127138

128139
ted::insert_all(
129140
ted::Position::before(enum_ast.syntax()),
@@ -279,7 +290,7 @@ fn create_struct_def(
279290
field_list.clone().into()
280291
}
281292
};
282-
field_list.reindent_to(IndentLevel::single());
293+
let field_list = field_list.indent(IndentLevel::single());
283294

284295
let strukt = make::struct_(enum_vis, name, generics, field_list).clone_for_update();
285296

src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,13 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
114114
let source_scope = ctx.sema.scope(v.syntax());
115115
let target_scope = ctx.sema.scope(strukt.syntax());
116116
if let (Some(s), Some(t)) = (source_scope, target_scope) {
117-
PathTransform::generic_transformation(&t, &s).apply(v.syntax());
117+
ast::Fn::cast(
118+
PathTransform::generic_transformation(&t, &s).apply(v.syntax()),
119+
)
120+
.unwrap_or(v)
121+
} else {
122+
v
118123
}
119-
v
120124
}
121125
None => return,
122126
};

src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,6 @@ fn generate_impl(
255255
delegee: &Delegee,
256256
edition: Edition,
257257
) -> Option<ast::Impl> {
258-
let delegate: ast::Impl;
259258
let db = ctx.db();
260259
let ast_strukt = &strukt.strukt;
261260
let strukt_ty = make::ty_path(make::ext::ident_path(&strukt.name.to_string()));
@@ -266,7 +265,7 @@ fn generate_impl(
266265
let bound_def = ctx.sema.source(delegee.to_owned())?.value;
267266
let bound_params = bound_def.generic_param_list();
268267

269-
delegate = make::impl_trait(
268+
let delegate = make::impl_trait(
270269
delegee.is_unsafe(db),
271270
bound_params.clone(),
272271
bound_params.map(|params| params.to_generic_args()),
@@ -304,7 +303,7 @@ fn generate_impl(
304303
let target_scope = ctx.sema.scope(strukt.strukt.syntax())?;
305304
let source_scope = ctx.sema.scope(bound_def.syntax())?;
306305
let transform = PathTransform::generic_transformation(&target_scope, &source_scope);
307-
transform.apply(delegate.syntax());
306+
ast::Impl::cast(transform.apply(delegate.syntax()))
308307
}
309308
Delegee::Impls(trait_, old_impl) => {
310309
let old_impl = ctx.sema.source(old_impl.to_owned())?.value;
@@ -358,20 +357,28 @@ fn generate_impl(
358357

359358
// 2.3) Instantiate generics with `transform_impl`, this step also
360359
// remove unused params.
361-
let mut trait_gen_args = old_impl.trait_()?.generic_arg_list();
362-
if let Some(trait_args) = &mut trait_gen_args {
363-
*trait_args = trait_args.clone_for_update();
364-
transform_impl(ctx, ast_strukt, &old_impl, &transform_args, trait_args.syntax())?;
365-
}
360+
let trait_gen_args = old_impl.trait_()?.generic_arg_list().and_then(|trait_args| {
361+
let trait_args = &mut trait_args.clone_for_update();
362+
if let Some(new_args) = transform_impl(
363+
ctx,
364+
ast_strukt,
365+
&old_impl,
366+
&transform_args,
367+
trait_args.clone_subtree(),
368+
) {
369+
*trait_args = new_args.clone_subtree();
370+
Some(new_args)
371+
} else {
372+
None
373+
}
374+
});
366375

367376
let type_gen_args = strukt_params.clone().map(|params| params.to_generic_args());
368-
369377
let path_type =
370378
make::ty(&trait_.name(db).display_no_db(edition).to_smolstr()).clone_for_update();
371-
transform_impl(ctx, ast_strukt, &old_impl, &transform_args, path_type.syntax())?;
372-
379+
let path_type = transform_impl(ctx, ast_strukt, &old_impl, &transform_args, path_type)?;
373380
// 3) Generate delegate trait impl
374-
delegate = make::impl_trait(
381+
let delegate = make::impl_trait(
375382
trait_.is_unsafe(db),
376383
trait_gen_params,
377384
trait_gen_args,
@@ -385,7 +392,6 @@ fn generate_impl(
385392
None,
386393
)
387394
.clone_for_update();
388-
389395
// Goto link : https://doc.rust-lang.org/reference/paths.html#qualified-paths
390396
let qualified_path_type =
391397
make::path_from_text(&format!("<{} as {}>", field_ty, delegate.trait_()?));
@@ -398,7 +404,7 @@ fn generate_impl(
398404
.filter(|item| matches!(item, AssocItem::MacroCall(_)).not())
399405
{
400406
let item = item.clone_for_update();
401-
transform_impl(ctx, ast_strukt, &old_impl, &transform_args, item.syntax())?;
407+
let item = transform_impl(ctx, ast_strukt, &old_impl, &transform_args, item)?;
402408

403409
let assoc = process_assoc_item(item, qualified_path_type.clone(), field_name)?;
404410
delegate_assoc_items.add_item(assoc);
@@ -408,19 +414,18 @@ fn generate_impl(
408414
if let Some(wc) = delegate.where_clause() {
409415
remove_useless_where_clauses(&delegate.trait_()?, &delegate.self_ty()?, wc);
410416
}
417+
Some(delegate)
411418
}
412419
}
413-
414-
Some(delegate)
415420
}
416421

417-
fn transform_impl(
422+
fn transform_impl<N: ast::AstNode>(
418423
ctx: &AssistContext<'_>,
419424
strukt: &ast::Struct,
420425
old_impl: &ast::Impl,
421426
args: &Option<GenericArgList>,
422-
syntax: &syntax::SyntaxNode,
423-
) -> Option<()> {
427+
syntax: N,
428+
) -> Option<N> {
424429
let source_scope = ctx.sema.scope(old_impl.self_ty()?.syntax())?;
425430
let target_scope = ctx.sema.scope(strukt.syntax())?;
426431
let hir_old_impl = ctx.sema.to_impl_def(old_impl)?;
@@ -437,8 +442,7 @@ fn transform_impl(
437442
},
438443
);
439444

440-
transform.apply(syntax);
441-
Some(())
445+
N::cast(transform.apply(syntax.syntax()))
442446
}
443447

444448
fn remove_instantiated_params(
@@ -570,9 +574,7 @@ where
570574
let scope = ctx.sema.scope(item.syntax())?;
571575

572576
let transform = PathTransform::adt_transformation(&scope, &scope, hir_adt, args.clone());
573-
transform.apply(item.syntax());
574-
575-
Some(item)
577+
N::cast(transform.apply(item.syntax()))
576578
}
577579

578580
fn has_self_type(trait_: hir::Trait, ctx: &AssistContext<'_>) -> Option<()> {

src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -743,17 +743,30 @@ fn fn_generic_params(
743743
let where_preds: Vec<ast::WherePred> =
744744
where_preds.into_iter().map(|it| it.node.clone_for_update()).collect();
745745

746-
// 4. Rewrite paths
747-
if let Some(param) = generic_params.first() {
748-
let source_scope = ctx.sema.scope(param.syntax())?;
749-
let target_scope = ctx.sema.scope(&target.parent())?;
750-
if source_scope.module() != target_scope.module() {
746+
let (generic_params, where_preds): (Vec<ast::GenericParam>, Vec<ast::WherePred>) =
747+
if let Some(param) = generic_params.first()
748+
&& let source_scope = ctx.sema.scope(param.syntax())?
749+
&& let target_scope = ctx.sema.scope(&target.parent())?
750+
&& source_scope.module() != target_scope.module()
751+
{
752+
// 4. Rewrite paths
751753
let transform = PathTransform::generic_transformation(&target_scope, &source_scope);
752754
let generic_params = generic_params.iter().map(|it| it.syntax());
753755
let where_preds = where_preds.iter().map(|it| it.syntax());
754-
transform.apply_all(generic_params.chain(where_preds));
755-
}
756-
}
756+
transform
757+
.apply_all(generic_params.chain(where_preds))
758+
.into_iter()
759+
.filter_map(|it| {
760+
if let Some(it) = ast::GenericParam::cast(it.clone()) {
761+
Some(either::Either::Left(it))
762+
} else {
763+
ast::WherePred::cast(it).map(either::Either::Right)
764+
}
765+
})
766+
.partition_map(|it| it)
767+
} else {
768+
(generic_params, where_preds)
769+
};
757770

758771
let generic_param_list = make::generic_param_list(generic_params);
759772
let where_clause =

src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -537,8 +537,13 @@ fn inline(
537537
if let Some(generic_arg_list) = generic_arg_list.clone() {
538538
if let Some((target, source)) = &sema.scope(node.syntax()).zip(sema.scope(fn_body.syntax()))
539539
{
540-
PathTransform::function_call(target, source, function, generic_arg_list)
541-
.apply(body.syntax());
540+
body.reindent_to(IndentLevel(0));
541+
if let Some(new_body) = ast::BlockExpr::cast(
542+
PathTransform::function_call(target, source, function, generic_arg_list)
543+
.apply(body.syntax()),
544+
) {
545+
body = new_body;
546+
}
542547
}
543548
}
544549

src/tools/rust-analyzer/crates/ide-assists/src/utils.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ pub fn add_trait_assoc_items_to_impl(
191191
original_items
192192
.iter()
193193
.map(|InFile { file_id, value: original_item }| {
194-
let cloned_item = {
194+
let mut cloned_item = {
195195
if let Some(macro_file) = file_id.macro_file() {
196196
let span_map = sema.db.expansion_span_map(macro_file);
197197
let item_prettified = prettify_macro_expansion(
@@ -207,17 +207,18 @@ pub fn add_trait_assoc_items_to_impl(
207207
}
208208
}
209209
original_item.clone_for_update()
210-
};
210+
}
211+
.reset_indent();
211212

212213
if let Some(source_scope) = sema.scope(original_item.syntax()) {
213214
// FIXME: Paths in nested macros are not handled well. See
214215
// `add_missing_impl_members::paths_in_nested_macro_should_get_transformed` test.
215216
let transform =
216217
PathTransform::trait_impl(target_scope, &source_scope, trait_, impl_.clone());
217-
transform.apply(cloned_item.syntax());
218+
cloned_item = ast::AssocItem::cast(transform.apply(cloned_item.syntax())).unwrap();
218219
}
219220
cloned_item.remove_attrs_and_docs();
220-
cloned_item.reset_indent()
221+
cloned_item
221222
})
222223
.map(|item| {
223224
match &item {

src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ fn get_transformed_assoc_item(
276276
let assoc_item = assoc_item.clone_for_update();
277277
// FIXME: Paths in nested macros are not handled well. See
278278
// `macro_generated_assoc_item2` test.
279-
transform.apply(assoc_item.syntax());
279+
let assoc_item = ast::AssocItem::cast(transform.apply(assoc_item.syntax()))?;
280280
assoc_item.remove_attrs_and_docs();
281281
Some(assoc_item)
282282
}
@@ -301,7 +301,7 @@ fn get_transformed_fn(
301301
let fn_ = fn_.clone_for_update();
302302
// FIXME: Paths in nested macros are not handled well. See
303303
// `macro_generated_assoc_item2` test.
304-
transform.apply(fn_.syntax());
304+
let fn_ = ast::Fn::cast(transform.apply(fn_.syntax()))?;
305305
fn_.remove_attrs_and_docs();
306306
match async_ {
307307
AsyncSugaring::Desugar => {

0 commit comments

Comments
 (0)