Skip to content

Commit

Permalink
Correctly generate new struct field in file containing struct def
Browse files Browse the repository at this point in the history
  • Loading branch information
TimoFreiberg committed Jun 22, 2020
1 parent ceb6920 commit 4bcaabe
Showing 1 changed file with 44 additions and 4 deletions.
48 changes: 44 additions & 4 deletions crates/ra_ide/src/diagnostics.rs
Expand Up @@ -138,33 +138,38 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>

fn missing_struct_field_fix(
sema: &Semantics<RootDatabase>,
file_id: FileId,
usage_file_id: FileId,
d: &hir::diagnostics::NoSuchField,
) -> Option<Fix> {
let record_expr = sema.ast(d);

let record_lit = ast::RecordLit::cast(record_expr.syntax().parent()?.parent()?)?;
let def_id = sema.resolve_variant(record_lit)?;
let module;
let def_file_id;
let record_fields = match VariantDef::from(def_id) {
VariantDef::Struct(s) => {
module = s.module(sema.db);
let source = s.source(sema.db);
def_file_id = source.file_id;
let fields = source.value.field_def_list()?;
record_field_def_list(fields)?
}
VariantDef::Union(u) => {
module = u.module(sema.db);
let source = u.source(sema.db);
def_file_id = source.file_id;
source.value.record_field_def_list()?
}
VariantDef::EnumVariant(e) => {
module = e.module(sema.db);
let source = e.source(sema.db);
def_file_id = source.file_id;
let fields = source.value.field_def_list()?;
record_field_def_list(fields)?
}
};
let def_file_id = def_file_id.original_file(sema.db);

let new_field_type = sema.type_of_expr(&record_expr.expr()?)?;
if new_field_type.is_unknown() {
Expand All @@ -179,15 +184,19 @@ fn missing_struct_field_fix(
let last_field_syntax = last_field.syntax();
let indent = IndentLevel::from_node(last_field_syntax);

let mut new_field = format!("\n{}{}", indent, new_field);
let mut new_field = new_field.to_string();
if usage_file_id != def_file_id {
new_field = format!("pub(crate) {}", new_field);
}
new_field = format!("\n{}{}", indent, new_field);

let needs_comma = !last_field_syntax.to_string().ends_with(",");
if needs_comma {
new_field = format!(",{}", new_field);
}

let source_change = SourceFileEdit {
file_id,
file_id: def_file_id,
edit: TextEdit::insert(last_field_syntax.text_range().end(), new_field),
};
let fix = Fix::new("Create field", source_change.into());
Expand Down Expand Up @@ -362,7 +371,12 @@ mod tests {
}

fn check_apply_diagnostic_fix(before: &str, after: &str) {
let (analysis, file_id) = single_file(before);
let (analysis, file_id) = if before.contains("//-") {
let (analysis, pos) = analysis_and_position(before);
(analysis, pos.file_id)
} else {
single_file(before)
};
let diagnostic = analysis.diagnostics(file_id).unwrap().pop().unwrap();
let mut fix = diagnostic.fix.unwrap();
let edit = fix.source_change.source_file_edits.pop().unwrap().edit;
Expand Down Expand Up @@ -888,4 +902,30 @@ fn main() {
",
)
}

#[test]
#[ignore]
// FIXME this test fails because no diagnostics are found
fn test_add_field_in_other_file_from_usage() {
check_apply_diagnostic_fix(
r"
//- /main.rs
mod foo;
fn main() {
Foo { bar: 3, <|>baz: false};
}
//- /foo.rs
struct Foo {
bar: i32
}
",
r"
struct Foo {
bar: i32,
baz: bool
}
",
)
}
}

0 comments on commit 4bcaabe

Please sign in to comment.