Unnamed repository; edit this file 'description' to name the repository.
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
96
97
98
99
100
101
//! Renderer for `enum` variants.

use hir::{HasAttrs, StructKind};
use ide_db::SymbolKind;
use syntax::SmolStr;

use crate::{
    item::{CompletionItem, ImportEdit},
    render::{
        compound::{format_literal_label, render_record, render_tuple, RenderedCompound},
        compute_ref_match, compute_type_match, RenderContext,
    },
    CompletionRelevance,
};

pub(crate) fn render_variant(
    ctx: RenderContext<'_>,
    import_to_add: Option<ImportEdit>,
    local_name: Option<hir::Name>,
    variant: hir::Variant,
    path: Option<hir::ModPath>,
) -> CompletionItem {
    let _p = profile::span("render_enum_variant");
    render(ctx, local_name, variant, path, import_to_add)
}

fn render(
    ctx @ RenderContext { completion, .. }: RenderContext<'_>,
    local_name: Option<hir::Name>,
    variant: hir::Variant,
    path: Option<hir::ModPath>,
    import_to_add: Option<ImportEdit>,
) -> CompletionItem {
    let db = completion.db;
    let name = local_name.unwrap_or_else(|| variant.name(db));
    let variant_kind = variant.kind(db);

    let (qualified_name, short_qualified_name, qualified) = match path {
        Some(path) => {
            let short = hir::ModPath::from_segments(
                hir::PathKind::Plain,
                path.segments().iter().skip(path.segments().len().saturating_sub(2)).cloned(),
            );
            (path, short, true)
        }
        None => (name.clone().into(), name.into(), false),
    };
    let qualified_name = qualified_name.to_string();
    let short_qualified_name: SmolStr = short_qualified_name.to_string().into();

    let mut rendered = match variant_kind {
        StructKind::Tuple => {
            render_tuple(db, ctx.snippet_cap(), &variant.fields(db), Some(&qualified_name))
        }
        StructKind::Record => {
            render_record(db, ctx.snippet_cap(), &variant.fields(db), Some(&qualified_name))
        }
        StructKind::Unit => {
            RenderedCompound { literal: qualified_name.clone(), detail: qualified_name.clone() }
        }
    };

    if ctx.snippet_cap().is_some() {
        rendered.literal.push_str("$0");
    }

    let mut item = CompletionItem::new(
        SymbolKind::Variant,
        ctx.source_range(),
        format_literal_label(&qualified_name, variant_kind),
    );

    item.set_documentation(variant.docs(db))
        .set_deprecated(ctx.is_deprecated(variant))
        .detail(rendered.detail);

    match ctx.snippet_cap() {
        Some(snippet_cap) => item.insert_snippet(snippet_cap, rendered.literal),
        None => item.insert_text(rendered.literal),
    };

    if let Some(import_to_add) = import_to_add {
        item.add_import(import_to_add);
    }

    if qualified {
        item.lookup_by(short_qualified_name);
    }

    let ty = variant.parent_enum(completion.db).ty(completion.db);
    item.set_relevance(CompletionRelevance {
        type_match: compute_type_match(completion, &ty),
        ..ctx.completion_relevance()
    });

    if let Some(ref_match) = compute_ref_match(completion, &ty) {
        item.ref_match(ref_match);
    }

    item.build()
}