aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/completion/complete_struct_literal.rs
blob: 893056c2b933cb644c9688d896393ca57eb4fdda (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
use hir::{Ty, AdtDef, Docs};

use crate::completion::{CompletionContext, Completions, CompletionItem, CompletionItemKind};
use crate::completion::completion_item::CompletionKind;

/// Complete dot accesses, i.e. fields or methods (currently only fields).
pub(super) fn complete_struct_literal(acc: &mut Completions, ctx: &CompletionContext) {
    let (function, struct_lit) = match (&ctx.function, ctx.struct_lit_syntax) {
        (Some(function), Some(struct_lit)) => (function, struct_lit),
        _ => return,
    };
    let infer_result = function.infer(ctx.db);
    let syntax_mapping = function.body_syntax_mapping(ctx.db);
    let expr = match syntax_mapping.node_expr(struct_lit.into()) {
        Some(expr) => expr,
        None => return,
    };
    let ty = infer_result[expr].clone();
    let (adt, substs) = match ty {
        Ty::Adt { def_id, ref substs, .. } => (def_id, substs),
        _ => return,
    };
    match adt {
        AdtDef::Struct(s) => {
            for field in s.fields(ctx.db) {
                CompletionItem::new(
                    CompletionKind::Reference,
                    ctx.source_range(),
                    field.name(ctx.db).to_string(),
                )
                .kind(CompletionItemKind::Field)
                .detail(field.ty(ctx.db).subst(substs).to_string())
                .set_documentation(field.docs(ctx.db))
                .add_to(acc);
            }
        }

        // TODO unions
        AdtDef::Enum(_) => (),
    };
}

#[cfg(test)]
mod tests {
    use crate::completion::*;
    use crate::completion::completion_item::check_completion;

    fn check_ref_completion(name: &str, code: &str) {
        check_completion(name, code, CompletionKind::Reference);
    }

    #[test]
    fn test_struct_literal_field() {
        check_ref_completion(
            "test_struct_literal_field",
            r"
            struct A { the_field: u32 }
            fn foo() {
               A { the<|> }
            }
            ",
        );
    }
}