mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-02 03:33:59 +00:00
Merge #989
989: Implement naive version of fill_struct_fields assist r=matklad a=yanchith Fixes #964 This implements the `fill_struct_fields` assist. Currently only works for named struct fields, but not for tuple structs, because we seem to be missing a `TupleStructLit` (akin to `StructLit`, but for tuple structs). I am happy to implement `TupleStructLit` parsing given some guidance (provided it's really missing) and make the assist work for tuple structs as well. Could do so either in this PR, or another one 🙂 Sorry if I missed something important, this is my first PR for Rust Analyzer. Btw is there any way to run the assists in emacs? UPDATE: I just realized that parsing `TupleStructLit` would be quite difficult as it it really similar, if not identical to a function call... Co-authored-by: yanchith <yanchi.toth@gmail.com>
This commit is contained in:
commit
7c117567ab
151
crates/ra_assists/src/fill_struct_fields.rs
Normal file
151
crates/ra_assists/src/fill_struct_fields.rs
Normal file
@ -0,0 +1,151 @@
|
||||
use std::fmt::Write;
|
||||
|
||||
use hir::{AdtDef, Ty, source_binder};
|
||||
use hir::db::HirDatabase;
|
||||
|
||||
use ra_syntax::ast::{self, AstNode};
|
||||
|
||||
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>()?;
|
||||
let named_field_list = struct_lit.named_field_list()?;
|
||||
|
||||
// If we already have existing struct fields, don't provide the assist.
|
||||
if named_field_list.fields().count() > 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
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(struct_lit.into())?;
|
||||
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 db = ctx.db;
|
||||
ctx.add_action(AssistId("fill_struct_fields"), "fill struct fields", |edit| {
|
||||
let mut buf = String::from("{\n");
|
||||
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(struct_lit.syntax().range().start());
|
||||
edit.replace_node_and_indent(named_field_list.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 {}",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fill_struct_fields_preserve_self() {
|
||||
check_assist(
|
||||
fill_struct_fields,
|
||||
r#"
|
||||
struct Foo {
|
||||
foo: u8,
|
||||
bar: String,
|
||||
baz: i128,
|
||||
}
|
||||
|
||||
impl Foo {
|
||||
pub fn new() -> Self {
|
||||
Self <|>{}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
struct Foo {
|
||||
foo: u8,
|
||||
bar: String,
|
||||
baz: i128,
|
||||
}
|
||||
|
||||
impl Foo {
|
||||
pub fn new() -> Self {
|
||||
<|>Self {
|
||||
foo: (),
|
||||
bar: (),
|
||||
baz: (),
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
}
|
@ -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;
|
||||
@ -103,6 +104,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,
|
||||
|
Loading…
Reference in New Issue
Block a user