aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/completion/complete_path.rs
blob: aaa2c7ceec10844564cb07bd1f70f78e79c88adc (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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use crate::{
    Cancelable,
    completion::{CompletionItem, Completions, CompletionKind, CompletionContext},
};

pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) -> Cancelable<()> {
    let (path, module) = match (&ctx.path_prefix, &ctx.module) {
        (Some(path), Some(module)) => (path.clone(), module),
        _ => return Ok(()),
    };
    let def_id = match module.resolve_path(ctx.db, &path)?.take_types() {
        Some(it) => it,
        None => return Ok(()),
    };
    let target_module = match def_id.resolve(ctx.db)? {
        hir::Def::Module(it) => it,
        _ => return Ok(()),
    };
    let module_scope = target_module.scope(ctx.db)?;
    module_scope.entries().for_each(|(name, res)| {
        CompletionItem::new(CompletionKind::Reference, name.to_string())
            .from_resolution(ctx.db, res)
            .add_to(acc)
    });
    Ok(())
}

#[cfg(test)]
mod tests {
    use crate::completion::{CompletionKind, check_completion};

    fn check_reference_completion(code: &str, expected_completions: &str) {
        check_completion(code, expected_completions, CompletionKind::Reference);
    }

    #[test]
    fn completes_use_item_starting_with_self() {
        check_reference_completion(
            r"
            use self::m::<|>;

            mod m {
                struct Bar;
            }
            ",
            "Bar",
        );
    }

    #[test]
    fn completes_use_item_starting_with_crate() {
        check_reference_completion(
            "
            //- /lib.rs
            mod foo;
            struct Spam;
            //- /foo.rs
            use crate::Sp<|>
            ",
            "Spam;foo",
        );
    }

    #[test]
    fn completes_nested_use_tree() {
        check_reference_completion(
            "
            //- /lib.rs
            mod foo;
            struct Spam;
            //- /foo.rs
            use crate::{Sp<|>};
            ",
            "Spam;foo",
        );
    }

    #[test]
    fn completes_deeply_nested_use_tree() {
        check_reference_completion(
            "
            //- /lib.rs
            mod foo;
            pub mod bar {
                pub mod baz {
                    pub struct Spam;
                }
            }
            //- /foo.rs
            use crate::{bar::{baz::Sp<|>}};
            ",
            "Spam",
        );
    }
}