mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-11-03 13:13:18 +00:00 
			
		
		
		
	Implement naive version of fill_struct_fields assist
This commit is contained in:
		
							parent
							
								
									cd9e93aa14
								
							
						
					
					
						commit
						907f7307af
					
				
							
								
								
									
										120
									
								
								crates/ra_assists/src/fill_struct_fields.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								crates/ra_assists/src/fill_struct_fields.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,120 @@
 | 
				
			|||||||
 | 
					use std::fmt::Write;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use hir::{AdtDef, Ty, source_binder};
 | 
				
			||||||
 | 
					use hir::db::HirDatabase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use ra_syntax::ast::{self, AstNode, Expr};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::{AssistCtx, Assist, AssistId};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub(crate) fn fill_struct_fields(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
 | 
				
			||||||
 | 
					    let struct_lit = ctx.node_at_offset::<ast::StructLit>()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // If we already have existing struct fields, don't provide the assist.
 | 
				
			||||||
 | 
					    // TODO: provide assist for tuple structs
 | 
				
			||||||
 | 
					    match struct_lit.named_field_list() {
 | 
				
			||||||
 | 
					        Some(named_field_list) if named_field_list.fields().count() > 0 => {
 | 
				
			||||||
 | 
					            return None;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        _ => {}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let expr: &Expr = struct_lit.into();
 | 
				
			||||||
 | 
					    let function =
 | 
				
			||||||
 | 
					        source_binder::function_from_child_node(ctx.db, ctx.frange.file_id, struct_lit.syntax())?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let infer_result = function.infer(ctx.db);
 | 
				
			||||||
 | 
					    let source_map = function.body_source_map(ctx.db);
 | 
				
			||||||
 | 
					    let node_expr = source_map.node_expr(expr)?;
 | 
				
			||||||
 | 
					    let struct_lit_ty = infer_result[node_expr].clone();
 | 
				
			||||||
 | 
					    let struct_def = match struct_lit_ty {
 | 
				
			||||||
 | 
					        Ty::Adt { def_id: AdtDef::Struct(s), .. } => s,
 | 
				
			||||||
 | 
					        _ => return None,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let struct_name = struct_def.name(ctx.db)?;
 | 
				
			||||||
 | 
					    let db = ctx.db;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ctx.add_action(AssistId("fill_struct_fields"), "fill struct fields", |edit| {
 | 
				
			||||||
 | 
					        let mut buf = format!("{} {{\n", struct_name);
 | 
				
			||||||
 | 
					        let struct_fields = struct_def.fields(db);
 | 
				
			||||||
 | 
					        for field in struct_fields {
 | 
				
			||||||
 | 
					            let field_name = field.name(db).to_string();
 | 
				
			||||||
 | 
					            write!(&mut buf, "    {}: (),\n", field_name).unwrap();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        buf.push_str("}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        edit.target(struct_lit.syntax().range());
 | 
				
			||||||
 | 
					        edit.set_cursor(expr.syntax().range().start());
 | 
				
			||||||
 | 
					        edit.replace_node_and_indent(struct_lit.syntax(), buf);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ctx.build()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cfg(test)]
 | 
				
			||||||
 | 
					mod tests {
 | 
				
			||||||
 | 
					    use crate::helpers::{check_assist, check_assist_target};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    use super::fill_struct_fields;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn fill_struct_fields_empty_body() {
 | 
				
			||||||
 | 
					        check_assist(
 | 
				
			||||||
 | 
					            fill_struct_fields,
 | 
				
			||||||
 | 
					            r#"
 | 
				
			||||||
 | 
					            struct S<'a, D> {
 | 
				
			||||||
 | 
					                a: u32,
 | 
				
			||||||
 | 
					                b: String,
 | 
				
			||||||
 | 
					                c: (i32, i32),
 | 
				
			||||||
 | 
					                d: D,
 | 
				
			||||||
 | 
					                r: &'a str,
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            fn main() {
 | 
				
			||||||
 | 
					                let s = S<|> {}
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            "#,
 | 
				
			||||||
 | 
					            r#"
 | 
				
			||||||
 | 
					            struct S<'a, D> {
 | 
				
			||||||
 | 
					                a: u32,
 | 
				
			||||||
 | 
					                b: String,
 | 
				
			||||||
 | 
					                c: (i32, i32),
 | 
				
			||||||
 | 
					                d: D,
 | 
				
			||||||
 | 
					                r: &'a str,
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            fn main() {
 | 
				
			||||||
 | 
					                let s = <|>S {
 | 
				
			||||||
 | 
					                    a: (),
 | 
				
			||||||
 | 
					                    b: (),
 | 
				
			||||||
 | 
					                    c: (),
 | 
				
			||||||
 | 
					                    d: (),
 | 
				
			||||||
 | 
					                    r: (),
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            "#,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn fill_struct_fields_target() {
 | 
				
			||||||
 | 
					        check_assist_target(
 | 
				
			||||||
 | 
					            fill_struct_fields,
 | 
				
			||||||
 | 
					            r#"
 | 
				
			||||||
 | 
					            struct S<'a, D> {
 | 
				
			||||||
 | 
					                a: u32,
 | 
				
			||||||
 | 
					                b: String,
 | 
				
			||||||
 | 
					                c: (i32, i32),
 | 
				
			||||||
 | 
					                d: D,
 | 
				
			||||||
 | 
					                r: &'a str,
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            fn main() {
 | 
				
			||||||
 | 
					                let s = S<|> {}
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            "#,
 | 
				
			||||||
 | 
					            "S {}",
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -90,6 +90,7 @@ mod add_impl;
 | 
				
			|||||||
mod flip_comma;
 | 
					mod flip_comma;
 | 
				
			||||||
mod change_visibility;
 | 
					mod change_visibility;
 | 
				
			||||||
mod fill_match_arms;
 | 
					mod fill_match_arms;
 | 
				
			||||||
 | 
					mod fill_struct_fields;
 | 
				
			||||||
mod introduce_variable;
 | 
					mod introduce_variable;
 | 
				
			||||||
mod replace_if_let_with_match;
 | 
					mod replace_if_let_with_match;
 | 
				
			||||||
mod split_import;
 | 
					mod split_import;
 | 
				
			||||||
@ -102,6 +103,7 @@ fn all_assists<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assis
 | 
				
			|||||||
        add_impl::add_impl,
 | 
					        add_impl::add_impl,
 | 
				
			||||||
        change_visibility::change_visibility,
 | 
					        change_visibility::change_visibility,
 | 
				
			||||||
        fill_match_arms::fill_match_arms,
 | 
					        fill_match_arms::fill_match_arms,
 | 
				
			||||||
 | 
					        fill_struct_fields::fill_struct_fields,
 | 
				
			||||||
        flip_comma::flip_comma,
 | 
					        flip_comma::flip_comma,
 | 
				
			||||||
        introduce_variable::introduce_variable,
 | 
					        introduce_variable::introduce_variable,
 | 
				
			||||||
        replace_if_let_with_match::replace_if_let_with_match,
 | 
					        replace_if_let_with_match::replace_if_let_with_match,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user