Implement naive version of fill_struct_fields assist

This commit is contained in:
yanchith 2019-03-17 19:48:25 +01:00
parent cd9e93aa14
commit 907f7307af
2 changed files with 122 additions and 0 deletions

View 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 {}",
);
}
}

View file

@ -90,6 +90,7 @@ mod add_impl;
mod flip_comma;
mod change_visibility;
mod fill_match_arms;
mod fill_struct_fields;
mod introduce_variable;
mod replace_if_let_with_match;
mod split_import;
@ -102,6 +103,7 @@ fn all_assists<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assis
add_impl::add_impl,
change_visibility::change_visibility,
fill_match_arms::fill_match_arms,
fill_struct_fields::fill_struct_fields,
flip_comma::flip_comma,
introduce_variable::introduce_variable,
replace_if_let_with_match::replace_if_let_with_match,