diff options
-rw-r--r-- | crates/ide_assists/src/handlers/convert_tuple_struct_to_named_struct.rs | 129 |
1 files changed, 61 insertions, 68 deletions
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 0df96be03..994e1a01a 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 | |||
@@ -1,8 +1,7 @@ | |||
1 | use hir::{Adt, ModuleDef, Struct}; | ||
2 | use ide_db::defs::{Definition, NameRefClass}; | 1 | use ide_db::defs::{Definition, NameRefClass}; |
3 | use syntax::{ | 2 | use syntax::{ |
4 | ast::{self, AstNode, GenericParamsOwner, VisibilityOwner}, | 3 | ast::{self, AstNode, GenericParamsOwner, VisibilityOwner}, |
5 | match_ast, | 4 | match_ast, SyntaxNode, |
6 | }; | 5 | }; |
7 | 6 | ||
8 | use crate::{assist_context::AssistBuilder, AssistContext, AssistId, AssistKind, Assists}; | 7 | use crate::{assist_context::AssistBuilder, AssistContext, AssistId, AssistKind, Assists}; |
@@ -104,80 +103,74 @@ fn edit_struct_def( | |||
104 | fn edit_struct_references( | 103 | fn edit_struct_references( |
105 | ctx: &AssistContext, | 104 | ctx: &AssistContext, |
106 | edit: &mut AssistBuilder, | 105 | edit: &mut AssistBuilder, |
107 | strukt: Struct, | 106 | strukt: hir::Struct, |
108 | names: &[ast::Name], | 107 | names: &[ast::Name], |
109 | ) { | 108 | ) { |
110 | let strukt_def = Definition::ModuleDef(ModuleDef::Adt(Adt::Struct(strukt))); | 109 | let strukt_def = Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Struct(strukt))); |
111 | let usages = strukt_def.usages(&ctx.sema).include_self_kw_refs(true).all(); | 110 | let usages = strukt_def.usages(&ctx.sema).include_self_kw_refs(true).all(); |
112 | 111 | ||
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 | |||
113 | for (file_id, refs) in usages { | 169 | for (file_id, refs) in usages { |
114 | edit.edit_file(file_id); | 170 | edit.edit_file(file_id); |
115 | for r in refs { | 171 | for r in refs { |
116 | for node in r.name.syntax().ancestors() { | 172 | for node in r.name.syntax().ancestors() { |
117 | match_ast! { | 173 | edit_node(edit, node); |
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 | } | ||
181 | } | 174 | } |
182 | } | 175 | } |
183 | } | 176 | } |