diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-06-21 18:05:21 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2021-06-21 18:05:21 +0100 |
commit | f06ddbea6a038eb546d44cb71f2d4d9c055a8828 (patch) | |
tree | 9c39a29bdee4f45dcbd497c25350cbfbb0c5e9c3 | |
parent | 1b05dbba39d5a4d46f321dc962df99038cddbf21 (diff) | |
parent | ae823aa23f1c4fa55e71dd972d0b10c69148b0b4 (diff) |
Merge #9080
9080: Improve completion of cfg attributes r=JamieCunliffe a=JamieCunliffe
This will close #5398 and it also adds some completion for cfg options.
Co-authored-by: Jamie Cunliffe <[email protected]>
-rw-r--r-- | crates/base_db/src/fixture.rs | 3 | ||||
-rw-r--r-- | crates/base_db/src/input.rs | 13 | ||||
-rw-r--r-- | crates/cfg/src/lib.rs | 20 | ||||
-rw-r--r-- | crates/hir/src/lib.rs | 4 | ||||
-rw-r--r-- | crates/ide/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/attribute.rs | 15 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/attribute/cfg.rs | 112 | ||||
-rw-r--r-- | crates/project_model/src/workspace.rs | 11 |
8 files changed, 179 insertions, 0 deletions
diff --git a/crates/base_db/src/fixture.rs b/crates/base_db/src/fixture.rs index 6ce377710..7d5d12e63 100644 --- a/crates/base_db/src/fixture.rs +++ b/crates/base_db/src/fixture.rs | |||
@@ -128,6 +128,7 @@ impl ChangeFixture { | |||
128 | file_id, | 128 | file_id, |
129 | meta.edition, | 129 | meta.edition, |
130 | Some(crate_name.clone().into()), | 130 | Some(crate_name.clone().into()), |
131 | meta.cfg.clone(), | ||
131 | meta.cfg, | 132 | meta.cfg, |
132 | meta.env, | 133 | meta.env, |
133 | Default::default(), | 134 | Default::default(), |
@@ -157,6 +158,7 @@ impl ChangeFixture { | |||
157 | crate_root, | 158 | crate_root, |
158 | Edition::Edition2018, | 159 | Edition::Edition2018, |
159 | Some(CrateName::new("test").unwrap().into()), | 160 | Some(CrateName::new("test").unwrap().into()), |
161 | default_cfg.clone(), | ||
160 | default_cfg, | 162 | default_cfg, |
161 | Env::default(), | 163 | Env::default(), |
162 | Default::default(), | 164 | Default::default(), |
@@ -186,6 +188,7 @@ impl ChangeFixture { | |||
186 | Edition::Edition2021, | 188 | Edition::Edition2021, |
187 | Some(CrateDisplayName::from_canonical_name("core".to_string())), | 189 | Some(CrateDisplayName::from_canonical_name("core".to_string())), |
188 | CfgOptions::default(), | 190 | CfgOptions::default(), |
191 | CfgOptions::default(), | ||
189 | Env::default(), | 192 | Env::default(), |
190 | Vec::new(), | 193 | Vec::new(), |
191 | ); | 194 | ); |
diff --git a/crates/base_db/src/input.rs b/crates/base_db/src/input.rs index 23cb0c839..0c51a59a0 100644 --- a/crates/base_db/src/input.rs +++ b/crates/base_db/src/input.rs | |||
@@ -189,6 +189,7 @@ pub struct CrateData { | |||
189 | /// `Dependency` matters), this name should only be used for UI. | 189 | /// `Dependency` matters), this name should only be used for UI. |
190 | pub display_name: Option<CrateDisplayName>, | 190 | pub display_name: Option<CrateDisplayName>, |
191 | pub cfg_options: CfgOptions, | 191 | pub cfg_options: CfgOptions, |
192 | pub potential_cfg_options: CfgOptions, | ||
192 | pub env: Env, | 193 | pub env: Env, |
193 | pub dependencies: Vec<Dependency>, | 194 | pub dependencies: Vec<Dependency>, |
194 | pub proc_macro: Vec<ProcMacro>, | 195 | pub proc_macro: Vec<ProcMacro>, |
@@ -219,6 +220,7 @@ impl CrateGraph { | |||
219 | edition: Edition, | 220 | edition: Edition, |
220 | display_name: Option<CrateDisplayName>, | 221 | display_name: Option<CrateDisplayName>, |
221 | cfg_options: CfgOptions, | 222 | cfg_options: CfgOptions, |
223 | potential_cfg_options: CfgOptions, | ||
222 | env: Env, | 224 | env: Env, |
223 | proc_macro: Vec<ProcMacro>, | 225 | proc_macro: Vec<ProcMacro>, |
224 | ) -> CrateId { | 226 | ) -> CrateId { |
@@ -227,6 +229,7 @@ impl CrateGraph { | |||
227 | edition, | 229 | edition, |
228 | display_name, | 230 | display_name, |
229 | cfg_options, | 231 | cfg_options, |
232 | potential_cfg_options, | ||
230 | env, | 233 | env, |
231 | proc_macro, | 234 | proc_macro, |
232 | dependencies: Vec::new(), | 235 | dependencies: Vec::new(), |
@@ -504,6 +507,7 @@ mod tests { | |||
504 | Edition2018, | 507 | Edition2018, |
505 | None, | 508 | None, |
506 | CfgOptions::default(), | 509 | CfgOptions::default(), |
510 | CfgOptions::default(), | ||
507 | Env::default(), | 511 | Env::default(), |
508 | Default::default(), | 512 | Default::default(), |
509 | ); | 513 | ); |
@@ -512,6 +516,7 @@ mod tests { | |||
512 | Edition2018, | 516 | Edition2018, |
513 | None, | 517 | None, |
514 | CfgOptions::default(), | 518 | CfgOptions::default(), |
519 | CfgOptions::default(), | ||
515 | Env::default(), | 520 | Env::default(), |
516 | Default::default(), | 521 | Default::default(), |
517 | ); | 522 | ); |
@@ -520,6 +525,7 @@ mod tests { | |||
520 | Edition2018, | 525 | Edition2018, |
521 | None, | 526 | None, |
522 | CfgOptions::default(), | 527 | CfgOptions::default(), |
528 | CfgOptions::default(), | ||
523 | Env::default(), | 529 | Env::default(), |
524 | Default::default(), | 530 | Default::default(), |
525 | ); | 531 | ); |
@@ -536,6 +542,7 @@ mod tests { | |||
536 | Edition2018, | 542 | Edition2018, |
537 | None, | 543 | None, |
538 | CfgOptions::default(), | 544 | CfgOptions::default(), |
545 | CfgOptions::default(), | ||
539 | Env::default(), | 546 | Env::default(), |
540 | Default::default(), | 547 | Default::default(), |
541 | ); | 548 | ); |
@@ -544,6 +551,7 @@ mod tests { | |||
544 | Edition2018, | 551 | Edition2018, |
545 | None, | 552 | None, |
546 | CfgOptions::default(), | 553 | CfgOptions::default(), |
554 | CfgOptions::default(), | ||
547 | Env::default(), | 555 | Env::default(), |
548 | Default::default(), | 556 | Default::default(), |
549 | ); | 557 | ); |
@@ -559,6 +567,7 @@ mod tests { | |||
559 | Edition2018, | 567 | Edition2018, |
560 | None, | 568 | None, |
561 | CfgOptions::default(), | 569 | CfgOptions::default(), |
570 | CfgOptions::default(), | ||
562 | Env::default(), | 571 | Env::default(), |
563 | Default::default(), | 572 | Default::default(), |
564 | ); | 573 | ); |
@@ -567,6 +576,7 @@ mod tests { | |||
567 | Edition2018, | 576 | Edition2018, |
568 | None, | 577 | None, |
569 | CfgOptions::default(), | 578 | CfgOptions::default(), |
579 | CfgOptions::default(), | ||
570 | Env::default(), | 580 | Env::default(), |
571 | Default::default(), | 581 | Default::default(), |
572 | ); | 582 | ); |
@@ -575,6 +585,7 @@ mod tests { | |||
575 | Edition2018, | 585 | Edition2018, |
576 | None, | 586 | None, |
577 | CfgOptions::default(), | 587 | CfgOptions::default(), |
588 | CfgOptions::default(), | ||
578 | Env::default(), | 589 | Env::default(), |
579 | Default::default(), | 590 | Default::default(), |
580 | ); | 591 | ); |
@@ -590,6 +601,7 @@ mod tests { | |||
590 | Edition2018, | 601 | Edition2018, |
591 | None, | 602 | None, |
592 | CfgOptions::default(), | 603 | CfgOptions::default(), |
604 | CfgOptions::default(), | ||
593 | Env::default(), | 605 | Env::default(), |
594 | Default::default(), | 606 | Default::default(), |
595 | ); | 607 | ); |
@@ -598,6 +610,7 @@ mod tests { | |||
598 | Edition2018, | 610 | Edition2018, |
599 | None, | 611 | None, |
600 | CfgOptions::default(), | 612 | CfgOptions::default(), |
613 | CfgOptions::default(), | ||
601 | Env::default(), | 614 | Env::default(), |
602 | Default::default(), | 615 | Default::default(), |
603 | ); | 616 | ); |
diff --git a/crates/cfg/src/lib.rs b/crates/cfg/src/lib.rs index 916d39a0b..9a4baa636 100644 --- a/crates/cfg/src/lib.rs +++ b/crates/cfg/src/lib.rs | |||
@@ -50,6 +50,26 @@ impl CfgOptions { | |||
50 | self.enabled.remove(&atom); | 50 | self.enabled.remove(&atom); |
51 | } | 51 | } |
52 | } | 52 | } |
53 | |||
54 | pub fn get_cfg_keys(&self) -> Vec<&SmolStr> { | ||
55 | self.enabled | ||
56 | .iter() | ||
57 | .map(|x| match x { | ||
58 | CfgAtom::Flag(key) => key, | ||
59 | CfgAtom::KeyValue { key, .. } => key, | ||
60 | }) | ||
61 | .collect() | ||
62 | } | ||
63 | |||
64 | pub fn get_cfg_values(&self, cfg_key: &str) -> Vec<&SmolStr> { | ||
65 | self.enabled | ||
66 | .iter() | ||
67 | .filter_map(|x| match x { | ||
68 | CfgAtom::KeyValue { key, value } if cfg_key == key => Some(value), | ||
69 | _ => None, | ||
70 | }) | ||
71 | .collect() | ||
72 | } | ||
53 | } | 73 | } |
54 | 74 | ||
55 | #[derive(Clone, Debug, PartialEq, Eq)] | 75 | #[derive(Clone, Debug, PartialEq, Eq)] |
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 88490fea9..30cc34403 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -233,6 +233,10 @@ impl Crate { | |||
233 | pub fn cfg(&self, db: &dyn HirDatabase) -> CfgOptions { | 233 | pub fn cfg(&self, db: &dyn HirDatabase) -> CfgOptions { |
234 | db.crate_graph()[self.id].cfg_options.clone() | 234 | db.crate_graph()[self.id].cfg_options.clone() |
235 | } | 235 | } |
236 | |||
237 | pub fn potential_cfg(&self, db: &dyn HirDatabase) -> CfgOptions { | ||
238 | db.crate_graph()[self.id].potential_cfg_options.clone() | ||
239 | } | ||
236 | } | 240 | } |
237 | 241 | ||
238 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 242 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 3798f32cc..aac084012 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs | |||
@@ -217,6 +217,7 @@ impl Analysis { | |||
217 | file_id, | 217 | file_id, |
218 | Edition::Edition2018, | 218 | Edition::Edition2018, |
219 | None, | 219 | None, |
220 | cfg_options.clone(), | ||
220 | cfg_options, | 221 | cfg_options, |
221 | Env::default(), | 222 | Env::default(), |
222 | Default::default(), | 223 | Default::default(), |
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 | ||
18 | mod cfg; | ||
18 | mod derive; | 19 | mod derive; |
19 | mod lint; | 20 | mod lint; |
20 | mod repr; | 21 | mod 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..847e6529a --- /dev/null +++ b/crates/ide_completion/src/completions/attribute/cfg.rs | |||
@@ -0,0 +1,112 @@ | |||
1 | //! Completion for cfg | ||
2 | |||
3 | use std::iter; | ||
4 | |||
5 | use syntax::SyntaxKind; | ||
6 | |||
7 | use crate::{ | ||
8 | completions::Completions, context::CompletionContext, item::CompletionKind, CompletionItem, | ||
9 | CompletionItemKind, | ||
10 | }; | ||
11 | |||
12 | pub(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("target_arch") => KNOWN_ARCH.iter().for_each(add_completion), | ||
30 | Some("target_env") => KNOWN_ENV.iter().for_each(add_completion), | ||
31 | Some("target_os") => KNOWN_OS.iter().for_each(add_completion), | ||
32 | Some("target_vendor") => KNOWN_VENDOR.iter().for_each(add_completion), | ||
33 | Some("target_endian") => ["little", "big"].iter().for_each(add_completion), | ||
34 | Some(name) => { | ||
35 | ctx.krate.map(|krate| { | ||
36 | krate.potential_cfg(ctx.db).get_cfg_values(&name).iter().for_each(|s| { | ||
37 | let mut item = CompletionItem::new( | ||
38 | CompletionKind::Attribute, | ||
39 | ctx.source_range(), | ||
40 | s.as_str(), | ||
41 | ); | ||
42 | item.insert_text(format!(r#""{}""#, s)); | ||
43 | |||
44 | acc.add(item.build()); | ||
45 | }) | ||
46 | }); | ||
47 | } | ||
48 | None => { | ||
49 | ctx.krate.map(|krate| { | ||
50 | krate.potential_cfg(ctx.db).get_cfg_keys().iter().for_each(|s| { | ||
51 | let item = CompletionItem::new( | ||
52 | CompletionKind::Attribute, | ||
53 | ctx.source_range(), | ||
54 | s.as_str(), | ||
55 | ); | ||
56 | acc.add(item.build()); | ||
57 | }) | ||
58 | }); | ||
59 | } | ||
60 | }; | ||
61 | } | ||
62 | |||
63 | const KNOWN_ARCH: [&'static str; 19] = [ | ||
64 | "aarch64", | ||
65 | "arm", | ||
66 | "avr", | ||
67 | "hexagon", | ||
68 | "mips", | ||
69 | "mips64", | ||
70 | "msp430", | ||
71 | "nvptx64", | ||
72 | "powerpc", | ||
73 | "powerpc64", | ||
74 | "riscv32", | ||
75 | "riscv64", | ||
76 | "s390x", | ||
77 | "sparc", | ||
78 | "sparc64", | ||
79 | "wasm32", | ||
80 | "wasm64", | ||
81 | "x86", | ||
82 | "x86_64", | ||
83 | ]; | ||
84 | |||
85 | const KNOWN_ENV: [&'static str; 7] = | ||
86 | ["eabihf", "gnu", "gnueabihf", "msvc", "relibc", "sgx", "uclibc"]; | ||
87 | |||
88 | const KNOWN_OS: [&'static str; 20] = [ | ||
89 | "cuda", | ||
90 | "dragonfly", | ||
91 | "emscripten", | ||
92 | "freebsd", | ||
93 | "fuchsia", | ||
94 | "haiku", | ||
95 | "hermit", | ||
96 | "illumos", | ||
97 | "l4re", | ||
98 | "linux", | ||
99 | "netbsd", | ||
100 | "none", | ||
101 | "openbsd", | ||
102 | "psp", | ||
103 | "redox", | ||
104 | "solaris", | ||
105 | "uefi", | ||
106 | "unknown", | ||
107 | "vxworks", | ||
108 | "windows", | ||
109 | ]; | ||
110 | |||
111 | const KNOWN_VENDOR: [&'static str; 8] = | ||
112 | ["apple", "fortanix", "nvidia", "pc", "sony", "unknown", "wrs", "uwp"]; | ||
diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index d8217f714..e67ba2bd9 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs | |||
@@ -384,6 +384,7 @@ fn project_json_to_crate_graph( | |||
384 | file_id, | 384 | file_id, |
385 | krate.edition, | 385 | krate.edition, |
386 | krate.display_name.clone(), | 386 | krate.display_name.clone(), |
387 | cfg_options.clone(), | ||
387 | cfg_options, | 388 | cfg_options, |
388 | env, | 389 | env, |
389 | proc_macro.unwrap_or_default(), | 390 | proc_macro.unwrap_or_default(), |
@@ -580,6 +581,7 @@ fn detached_files_to_crate_graph( | |||
580 | Edition::Edition2018, | 581 | Edition::Edition2018, |
581 | display_name, | 582 | display_name, |
582 | cfg_options.clone(), | 583 | cfg_options.clone(), |
584 | cfg_options.clone(), | ||
583 | Env::default(), | 585 | Env::default(), |
584 | Vec::new(), | 586 | Vec::new(), |
585 | ); | 587 | ); |
@@ -719,11 +721,19 @@ fn add_target_crate_root( | |||
719 | .unwrap_or_default(); | 721 | .unwrap_or_default(); |
720 | 722 | ||
721 | let display_name = CrateDisplayName::from_canonical_name(cargo_name.to_string()); | 723 | let display_name = CrateDisplayName::from_canonical_name(cargo_name.to_string()); |
724 | let mut potential_cfg_options = cfg_options.clone(); | ||
725 | potential_cfg_options.extend( | ||
726 | pkg.features | ||
727 | .iter() | ||
728 | .map(|feat| CfgFlag::KeyValue { key: "feature".into(), value: feat.0.into() }), | ||
729 | ); | ||
730 | |||
722 | let crate_id = crate_graph.add_crate_root( | 731 | let crate_id = crate_graph.add_crate_root( |
723 | file_id, | 732 | file_id, |
724 | edition, | 733 | edition, |
725 | Some(display_name), | 734 | Some(display_name), |
726 | cfg_options, | 735 | cfg_options, |
736 | potential_cfg_options, | ||
727 | env, | 737 | env, |
728 | proc_macro, | 738 | proc_macro, |
729 | ); | 739 | ); |
@@ -753,6 +763,7 @@ fn sysroot_to_crate_graph( | |||
753 | Edition::Edition2018, | 763 | Edition::Edition2018, |
754 | Some(display_name), | 764 | Some(display_name), |
755 | cfg_options.clone(), | 765 | cfg_options.clone(), |
766 | cfg_options.clone(), | ||
756 | env, | 767 | env, |
757 | proc_macro, | 768 | proc_macro, |
758 | ); | 769 | ); |