|
1 |
| -use hir::{Adt, ModuleDef, Struct}; |
2 | 1 | use ide_db::defs::{Definition, NameRefClass};
|
3 | 2 | use syntax::{
|
4 | 3 | ast::{self, AstNode, GenericParamsOwner, VisibilityOwner},
|
5 |
| - match_ast, |
| 4 | + match_ast, SyntaxNode, |
6 | 5 | };
|
7 | 6 |
|
8 | 7 | use crate::{assist_context::AssistBuilder, AssistContext, AssistId, AssistKind, Assists};
|
@@ -104,80 +103,74 @@ fn edit_struct_def(
|
104 | 103 | fn edit_struct_references(
|
105 | 104 | ctx: &AssistContext,
|
106 | 105 | edit: &mut AssistBuilder,
|
107 |
| - strukt: Struct, |
| 106 | + strukt: hir::Struct, |
108 | 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 | 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 | 169 | for (file_id, refs) in usages {
|
114 | 170 | edit.edit_file(file_id);
|
115 | 171 | for r in refs {
|
116 | 172 | 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); |
181 | 174 | }
|
182 | 175 | }
|
183 | 176 | }
|
|
0 commit comments