diff options
-rw-r--r-- | crates/ide_assists/src/handlers/convert_tuple_struct_to_named_struct.rs | 28 |
1 files changed, 19 insertions, 9 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 ee6ddfbc6..086a44425 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,4 +1,4 @@ | |||
1 | use hir::{Adt, ModuleDef}; | 1 | use hir::{Adt, ModuleDef, Struct}; |
2 | use ide_db::defs::{Definition, NameRefClass}; | 2 | use ide_db::defs::{Definition, NameRefClass}; |
3 | use syntax::{ | 3 | use syntax::{ |
4 | ast::{self, AstNode, GenericParamsOwner, VisibilityOwner}, | 4 | ast::{self, AstNode, GenericParamsOwner, VisibilityOwner}, |
@@ -55,6 +55,7 @@ pub(crate) fn convert_tuple_struct_to_named_struct( | |||
55 | ast::FieldList::TupleFieldList(it) => it, | 55 | ast::FieldList::TupleFieldList(it) => it, |
56 | ast::FieldList::RecordFieldList(_) => return None, | 56 | ast::FieldList::RecordFieldList(_) => return None, |
57 | }; | 57 | }; |
58 | let strukt_def = ctx.sema.to_def(&strukt)?; | ||
58 | 59 | ||
59 | let target = strukt.syntax().text_range(); | 60 | let target = strukt.syntax().text_range(); |
60 | acc.add( | 61 | acc.add( |
@@ -64,7 +65,7 @@ pub(crate) fn convert_tuple_struct_to_named_struct( | |||
64 | |edit| { | 65 | |edit| { |
65 | let names = generate_names(tuple_fields.fields()); | 66 | let names = generate_names(tuple_fields.fields()); |
66 | edit_field_references(ctx, edit, tuple_fields.fields(), &names); | 67 | edit_field_references(ctx, edit, tuple_fields.fields(), &names); |
67 | edit_struct_references(ctx, edit, &strukt, &names); | 68 | edit_struct_references(ctx, edit, strukt_def, &names); |
68 | edit_struct_def(ctx, edit, &strukt, tuple_fields, names); | 69 | edit_struct_def(ctx, edit, &strukt, tuple_fields, names); |
69 | }, | 70 | }, |
70 | ) | 71 | ) |
@@ -80,7 +81,7 @@ fn edit_struct_def( | |||
80 | let record_fields = tuple_fields | 81 | let record_fields = tuple_fields |
81 | .fields() | 82 | .fields() |
82 | .zip(names) | 83 | .zip(names) |
83 | .map(|(f, name)| ast::make::record_field(f.visibility(), name, f.ty().unwrap())); | 84 | .filter_map(|(f, name)| Some(ast::make::record_field(f.visibility(), name, f.ty()?))); |
84 | let record_fields = ast::make::record_field_list(record_fields); | 85 | let record_fields = ast::make::record_field_list(record_fields); |
85 | let tuple_fields_text_range = tuple_fields.syntax().text_range(); | 86 | let tuple_fields_text_range = tuple_fields.syntax().text_range(); |
86 | 87 | ||
@@ -103,10 +104,9 @@ fn edit_struct_def( | |||
103 | fn edit_struct_references( | 104 | fn edit_struct_references( |
104 | ctx: &AssistContext, | 105 | ctx: &AssistContext, |
105 | edit: &mut AssistBuilder, | 106 | edit: &mut AssistBuilder, |
106 | strukt: &ast::Struct, | 107 | strukt: Struct, |
107 | names: &[ast::Name], | 108 | names: &[ast::Name], |
108 | ) { | 109 | ) { |
109 | let strukt = ctx.sema.to_def(strukt).unwrap(); | ||
110 | let strukt_def = Definition::ModuleDef(ModuleDef::Adt(Adt::Struct(strukt))); | 110 | let strukt_def = Definition::ModuleDef(ModuleDef::Adt(Adt::Struct(strukt))); |
111 | let usages = strukt_def.usages(&ctx.sema).include_self_kw_refs(true).all(); | 111 | let usages = strukt_def.usages(&ctx.sema).include_self_kw_refs(true).all(); |
112 | 112 | ||
@@ -117,10 +117,15 @@ fn edit_struct_references( | |||
117 | match_ast! { | 117 | match_ast! { |
118 | match node { | 118 | match node { |
119 | ast::TupleStructPat(tuple_struct_pat) => { | 119 | ast::TupleStructPat(tuple_struct_pat) => { |
120 | let path = match tuple_struct_pat.path() { | ||
121 | Some(it) => it, | ||
122 | None => continue, | ||
123 | }; | ||
124 | |||
120 | edit.replace( | 125 | edit.replace( |
121 | tuple_struct_pat.syntax().text_range(), | 126 | tuple_struct_pat.syntax().text_range(), |
122 | ast::make::record_pat_with_fields( | 127 | ast::make::record_pat_with_fields( |
123 | tuple_struct_pat.path().unwrap(), | 128 | path, |
124 | ast::make::record_pat_field_list(tuple_struct_pat.fields().zip(names).map( | 129 | ast::make::record_pat_field_list(tuple_struct_pat.fields().zip(names).map( |
125 | |(pat, name)| { | 130 | |(pat, name)| { |
126 | ast::make::record_pat_field( | 131 | ast::make::record_pat_field( |
@@ -135,7 +140,10 @@ fn edit_struct_references( | |||
135 | }, | 140 | }, |
136 | // for tuple struct creations like Foo(42) | 141 | // for tuple struct creations like Foo(42) |
137 | ast::CallExpr(call_expr) => { | 142 | ast::CallExpr(call_expr) => { |
138 | let path = call_expr.syntax().descendants().find_map(ast::PathExpr::cast).unwrap().path().unwrap(); | 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 | }; | ||
139 | 147 | ||
140 | // this also includes method calls like Foo::new(42), we should skip them | 148 | // this also includes method calls like Foo::new(42), we should skip them |
141 | if let Some(Some(name_ref)) = path.segment().map(|s| s.name_ref()) { | 149 | if let Some(Some(name_ref)) = path.segment().map(|s| s.name_ref()) { |
@@ -146,8 +154,10 @@ fn edit_struct_references( | |||
146 | }; | 154 | }; |
147 | } | 155 | } |
148 | 156 | ||
149 | let arg_list = | 157 | let arg_list = match call_expr.syntax().descendants().find_map(ast::ArgList::cast) { |
150 | call_expr.syntax().descendants().find_map(ast::ArgList::cast).unwrap(); | 158 | Some(it) => it, |
159 | None => continue, | ||
160 | }; | ||
151 | 161 | ||
152 | edit.replace( | 162 | edit.replace( |
153 | call_expr.syntax().text_range(), | 163 | call_expr.syntax().text_range(), |