aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion/src/completions
diff options
context:
space:
mode:
authorJamie Cunliffe <[email protected]>2021-05-30 14:52:19 +0100
committerJamie Cunliffe <[email protected]>2021-06-21 17:47:00 +0100
commit284483b347d15bee3a7bf293d33e5f19a9740102 (patch)
treee582a7ecdef30511b8982529f11889f1aab3ca5e /crates/ide_completion/src/completions
parent1b05dbba39d5a4d46f321dc962df99038cddbf21 (diff)
Improve completion of cfg attributes
The completion of cfg will look at the enabled cfg keys when performing completion. It will also look crate features when completing a feature cfg option. A fixed list of known values for some cfg options are provided. For unknown keys it will look at the enabled values for that cfg key, which means that completion will only show enabled options for those.
Diffstat (limited to 'crates/ide_completion/src/completions')
-rw-r--r--crates/ide_completion/src/completions/attribute.rs15
-rw-r--r--crates/ide_completion/src/completions/attribute/cfg.rs126
2 files changed, 141 insertions, 0 deletions
diff --git a/crates/ide_completion/src/completions/attribute.rs b/crates/ide_completion/src/completions/attribute.rs
index 78fc30e16..cc4f4b2af 100644
--- a/crates/ide_completion/src/completions/attribute.rs
+++ b/crates/ide_completion/src/completions/attribute.rs
@@ -15,6 +15,7 @@ use crate::{
15 Completions, 15 Completions,
16}; 16};
17 17
18mod cfg;
18mod derive; 19mod derive;
19mod lint; 20mod lint;
20mod repr; 21mod repr;
@@ -30,6 +31,9 @@ pub(crate) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext)
30 lint::complete_lint(acc, ctx, token_tree.clone(), DEFAULT_LINTS); 31 lint::complete_lint(acc, ctx, token_tree.clone(), DEFAULT_LINTS);
31 lint::complete_lint(acc, ctx, token_tree, CLIPPY_LINTS); 32 lint::complete_lint(acc, ctx, token_tree, CLIPPY_LINTS);
32 } 33 }
34 "cfg" => {
35 cfg::complete_cfg(acc, ctx);
36 }
33 _ => (), 37 _ => (),
34 }, 38 },
35 (None, Some(_)) => (), 39 (None, Some(_)) => (),
@@ -852,4 +856,15 @@ mod tests {
852 "#]], 856 "#]],
853 ); 857 );
854 } 858 }
859
860 #[test]
861 fn test_cfg() {
862 check(
863 r#"#[cfg(target_endian = $0"#,
864 expect![[r#"
865 at little
866 at big
867"#]],
868 );
869 }
855} 870}
diff --git a/crates/ide_completion/src/completions/attribute/cfg.rs b/crates/ide_completion/src/completions/attribute/cfg.rs
new file mode 100644
index 000000000..71e659563
--- /dev/null
+++ b/crates/ide_completion/src/completions/attribute/cfg.rs
@@ -0,0 +1,126 @@
1//! Completion for cfg
2
3use std::iter;
4
5use syntax::SyntaxKind;
6
7use crate::{
8 completions::Completions, context::CompletionContext, item::CompletionKind, CompletionItem,
9 CompletionItemKind,
10};
11
12pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext) {
13 let add_completion = |item: &&str| {
14 let mut completion =
15 CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), *item);
16 completion.insert_text(format!(r#""{}""#, item));
17 completion.kind(CompletionItemKind::Attribute);
18 acc.add(completion.build());
19 };
20
21 let previous = iter::successors(ctx.original_token.prev_token(), |t| {
22 (matches!(t.kind(), SyntaxKind::EQ) || t.kind().is_trivia())
23 .then(|| t.prev_token())
24 .flatten()
25 })
26 .find(|t| matches!(t.kind(), SyntaxKind::IDENT));
27
28 match previous.as_ref().map(|p| p.text()) {
29 Some("feature") => {
30 ctx.krate.map(|krate| {
31 krate.features(ctx.db).iter().for_each(|f| {
32 let mut item = CompletionItem::new(
33 CompletionKind::Attribute,
34 ctx.source_range(),
35 f.clone(),
36 );
37 item.insert_text(format!(r#""{}""#, f));
38
39 acc.add(item.build())
40 })
41 });
42 }
43 Some("target_arch") => KNOWN_ARCH.iter().for_each(add_completion),
44 Some("target_env") => KNOWN_ENV.iter().for_each(add_completion),
45 Some("target_os") => KNOWN_OS.iter().for_each(add_completion),
46 Some("target_vendor") => KNOWN_VENDOR.iter().for_each(add_completion),
47 Some("target_endian") => ["little", "big"].iter().for_each(add_completion),
48 Some(name) => {
49 ctx.krate.map(|krate| {
50 krate.cfg(ctx.db).get_cfg_values(&name).iter().for_each(|s| {
51 let mut item = CompletionItem::new(
52 CompletionKind::Attribute,
53 ctx.source_range(),
54 s.as_str(),
55 );
56 item.insert_text(format!(r#""{}""#, s));
57
58 acc.add(item.build());
59 })
60 });
61 }
62 None => {
63 ctx.krate.map(|krate| {
64 krate.cfg(ctx.db).get_cfg_keys().iter().for_each(|s| {
65 let item = CompletionItem::new(
66 CompletionKind::Attribute,
67 ctx.source_range(),
68 s.as_str(),
69 );
70 acc.add(item.build());
71 })
72 });
73 }
74 };
75}
76
77const KNOWN_ARCH: [&'static str; 19] = [
78 "aarch64",
79 "arm",
80 "avr",
81 "hexagon",
82 "mips",
83 "mips64",
84 "msp430",
85 "nvptx64",
86 "powerpc",
87 "powerpc64",
88 "riscv32",
89 "riscv64",
90 "s390x",
91 "sparc",
92 "sparc64",
93 "wasm32",
94 "wasm64",
95 "x86",
96 "x86_64",
97];
98
99const KNOWN_ENV: [&'static str; 7] =
100 ["eabihf", "gnu", "gnueabihf", "msvc", "relibc", "sgx", "uclibc"];
101
102const KNOWN_OS: [&'static str; 20] = [
103 "cuda",
104 "dragonfly",
105 "emscripten",
106 "freebsd",
107 "fuchsia",
108 "haiku",
109 "hermit",
110 "illumos",
111 "l4re",
112 "linux",
113 "netbsd",
114 "none",
115 "openbsd",
116 "psp",
117 "redox",
118 "solaris",
119 "uefi",
120 "unknown",
121 "vxworks",
122 "windows",
123];
124
125const KNOWN_VENDOR: [&'static str; 8] =
126 ["apple", "fortanix", "nvidia", "pc", "sony", "unknown", "wrs", "uwp"];