Skip to content

Commit affd8d3

Browse files
committed
Move reference editing logic into own function to make error handling more ease in "Convert to named struct" assist
1 parent 322cd1f commit affd8d3

File tree

1 file changed

+61
-68
lines changed

1 file changed

+61
-68
lines changed

crates/ide_assists/src/handlers/convert_tuple_struct_to_named_struct.rs

Lines changed: 61 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
use hir::{Adt, ModuleDef, Struct};
21
use ide_db::defs::{Definition, NameRefClass};
32
use syntax::{
43
ast::{self, AstNode, GenericParamsOwner, VisibilityOwner},
5-
match_ast,
4+
match_ast, SyntaxNode,
65
};
76

87
use crate::{assist_context::AssistBuilder, AssistContext, AssistId, AssistKind, Assists};
@@ -104,80 +103,74 @@ fn edit_struct_def(
104103
fn edit_struct_references(
105104
ctx: &AssistContext,
106105
edit: &mut AssistBuilder,
107-
strukt: Struct,
106+
strukt: hir::Struct,
108107
names: &[ast::Name],
109108
) {
110-
let strukt_def = Definition::ModuleDef(ModuleDef::Adt(Adt::Struct(strukt)));
109+
let strukt_def = Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Struct(strukt)));
111110
let usages = strukt_def.usages(&ctx.sema).include_self_kw_refs(true).all();
112111

112+
let edit_node = |edit: &mut AssistBuilder, node: SyntaxNode| -> Option<()> {
113+
match_ast! {
114+
match node {
115+
ast::TupleStructPat(tuple_struct_pat) => {
116+
edit.replace(
117+
tuple_struct_pat.syntax().text_range(),
118+
ast::make::record_pat_with_fields(
119+
tuple_struct_pat.path()?,
120+
ast::make::record_pat_field_list(tuple_struct_pat.fields().zip(names).map(
121+
|(pat, name)| {
122+
ast::make::record_pat_field(
123+
ast::make::name_ref(&name.to_string()),
124+
pat,
125+
)
126+
},
127+
)),
128+
)
129+
.to_string(),
130+
);
131+
},
132+
// for tuple struct creations like Foo(42)
133+
ast::CallExpr(call_expr) => {
134+
let path = call_expr.syntax().descendants().find_map(ast::PathExpr::cast).and_then(|expr| expr.path())?;
135+
136+
// this also includes method calls like Foo::new(42), we should skip them
137+
if let Some(name_ref) = path.segment().and_then(|s| s.name_ref()) {
138+
match NameRefClass::classify(&ctx.sema, &name_ref) {
139+
Some(NameRefClass::Definition(Definition::SelfType(_))) => {},
140+
Some(NameRefClass::Definition(def)) if def == strukt_def => {},
141+
_ => return None,
142+
};
143+
}
144+
145+
let arg_list = call_expr.syntax().descendants().find_map(ast::ArgList::cast)?;
146+
147+
edit.replace(
148+
call_expr.syntax().text_range(),
149+
ast::make::record_expr(
150+
path,
151+
ast::make::record_expr_field_list(arg_list.args().zip(names).map(
152+
|(expr, name)| {
153+
ast::make::record_expr_field(
154+
ast::make::name_ref(&name.to_string()),
155+
Some(expr),
156+
)
157+
},
158+
)),
159+
)
160+
.to_string(),
161+
);
162+
},
163+
_ => ()
164+
}
165+
}
166+
Some(())
167+
};
168+
113169
for (file_id, refs) in usages {
114170
edit.edit_file(file_id);
115171
for r in refs {
116172
for node in r.name.syntax().ancestors() {
117-
match_ast! {
118-
match node {
119-
ast::TupleStructPat(tuple_struct_pat) => {
120-
let path = match tuple_struct_pat.path() {
121-
Some(it) => it,
122-
None => continue,
123-
};
124-
125-
edit.replace(
126-
tuple_struct_pat.syntax().text_range(),
127-
ast::make::record_pat_with_fields(
128-
path,
129-
ast::make::record_pat_field_list(tuple_struct_pat.fields().zip(names).map(
130-
|(pat, name)| {
131-
ast::make::record_pat_field(
132-
ast::make::name_ref(&name.to_string()),
133-
pat,
134-
)
135-
},
136-
)),
137-
)
138-
.to_string(),
139-
);
140-
},
141-
// for tuple struct creations like Foo(42)
142-
ast::CallExpr(call_expr) => {
143-
let path = match call_expr.syntax().descendants().find_map(ast::PathExpr::cast).map(|expr| expr.path()) {
144-
Some(Some(it)) => it,
145-
_ => continue,
146-
};
147-
148-
// this also includes method calls like Foo::new(42), we should skip them
149-
if let Some(Some(name_ref)) = path.segment().map(|s| s.name_ref()) {
150-
match NameRefClass::classify(&ctx.sema, &name_ref) {
151-
Some(NameRefClass::Definition(Definition::SelfType(_))) => {},
152-
Some(NameRefClass::Definition(def)) if def == strukt_def => {},
153-
_ => continue,
154-
};
155-
}
156-
157-
let arg_list = match call_expr.syntax().descendants().find_map(ast::ArgList::cast) {
158-
Some(it) => it,
159-
None => continue,
160-
};
161-
162-
edit.replace(
163-
call_expr.syntax().text_range(),
164-
ast::make::record_expr(
165-
path,
166-
ast::make::record_expr_field_list(arg_list.args().zip(names).map(
167-
|(expr, name)| {
168-
ast::make::record_expr_field(
169-
ast::make::name_ref(&name.to_string()),
170-
Some(expr),
171-
)
172-
},
173-
)),
174-
)
175-
.to_string(),
176-
);
177-
},
178-
_ => ()
179-
}
180-
}
173+
edit_node(edit, node);
181174
}
182175
}
183176
}

0 commit comments

Comments
 (0)