aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion/src/completions/attribute
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_completion/src/completions/attribute')
-rw-r--r--crates/ide_completion/src/completions/attribute/derive.rs66
-rw-r--r--crates/ide_completion/src/completions/attribute/lint.rs3
-rw-r--r--crates/ide_completion/src/completions/attribute/repr.rs199
3 files changed, 243 insertions, 25 deletions
diff --git a/crates/ide_completion/src/completions/attribute/derive.rs b/crates/ide_completion/src/completions/attribute/derive.rs
index d526824fb..6fe41e0d6 100644
--- a/crates/ide_completion/src/completions/attribute/derive.rs
+++ b/crates/ide_completion/src/completions/attribute/derive.rs
@@ -31,6 +31,8 @@ pub(super) fn complete_derive(
31 let lookup = components.join(", "); 31 let lookup = components.join(", ");
32 let label = components.iter().rev().join(", "); 32 let label = components.iter().rev().join(", ");
33 (label, Some(lookup)) 33 (label, Some(lookup))
34 } else if existing_derives.contains(&derive) {
35 continue;
34 } else { 36 } else {
35 (derive, None) 37 (derive, None)
36 }; 38 };
@@ -80,10 +82,31 @@ const DEFAULT_DERIVE_COMPLETIONS: &[DeriveDependencies] = &[
80mod tests { 82mod tests {
81 use expect_test::{expect, Expect}; 83 use expect_test::{expect, Expect};
82 84
83 use crate::{test_utils::completion_list, CompletionKind}; 85 use crate::tests::completion_list;
84 86
85 fn check(ra_fixture: &str, expect: Expect) { 87 fn check(ra_fixture: &str, expect: Expect) {
86 let actual = completion_list(ra_fixture, CompletionKind::Attribute); 88 let builtin_derives = r#"
89#[rustc_builtin_macro]
90pub macro Clone {}
91#[rustc_builtin_macro]
92pub macro Copy {}
93#[rustc_builtin_macro]
94pub macro Default {}
95#[rustc_builtin_macro]
96pub macro Debug {}
97#[rustc_builtin_macro]
98pub macro Hash {}
99#[rustc_builtin_macro]
100pub macro PartialEq {}
101#[rustc_builtin_macro]
102pub macro Eq {}
103#[rustc_builtin_macro]
104pub macro PartialOrd {}
105#[rustc_builtin_macro]
106pub macro Ord {}
107
108"#;
109 let actual = completion_list(&format!("{} {}", builtin_derives, ra_fixture));
87 expect.assert_eq(&actual); 110 expect.assert_eq(&actual);
88 } 111 }
89 112
@@ -93,56 +116,53 @@ mod tests {
93 } 116 }
94 117
95 #[test] 118 #[test]
96 #[ignore] // FIXME: Fixtures cant test proc-macros/derives yet as we cant specify them in fixtures
97 fn empty_derive() { 119 fn empty_derive() {
98 check( 120 check(
99 r#"#[derive($0)] struct Test;"#, 121 r#"#[derive($0)] struct Test;"#,
100 expect![[r#" 122 expect![[r#"
101 at Clone 123 at PartialEq
102 at Clone, Copy 124 at Default
103 at Debug 125 at PartialEq, Eq
104 at Default 126 at PartialEq, Eq, PartialOrd, Ord
105 at Hash 127 at Clone, Copy
106 at PartialEq 128 at Debug
107 at PartialEq, Eq 129 at Clone
108 at PartialEq, PartialOrd 130 at Hash
109 at PartialEq, Eq, PartialOrd, Ord 131 at PartialEq, PartialOrd
110 "#]], 132 "#]],
111 ); 133 );
112 } 134 }
113 135
114 #[test] 136 #[test]
115 #[ignore] // FIXME: Fixtures cant test proc-macros/derives yet as we cant specify them in fixtures
116 fn derive_with_input() { 137 fn derive_with_input() {
117 check( 138 check(
118 r#"#[derive(serde::Serialize, PartialEq, $0)] struct Test;"#, 139 r#"#[derive(serde::Serialize, PartialEq, $0)] struct Test;"#,
119 expect![[r#" 140 expect![[r#"
120 at Clone 141 at Default
142 at Eq
143 at Eq, PartialOrd, Ord
121 at Clone, Copy 144 at Clone, Copy
122 at Debug 145 at Debug
123 at Default 146 at Clone
124 at Hash 147 at Hash
125 at Eq
126 at PartialOrd 148 at PartialOrd
127 at Eq, PartialOrd, Ord
128 "#]], 149 "#]],
129 ) 150 )
130 } 151 }
131 152
132 #[test] 153 #[test]
133 #[ignore] // FIXME: Fixtures cant test proc-macros/derives yet as we cant specify them in fixtures
134 fn derive_with_input2() { 154 fn derive_with_input2() {
135 check( 155 check(
136 r#"#[derive($0 serde::Serialize, PartialEq)] struct Test;"#, 156 r#"#[derive($0 serde::Serialize, PartialEq)] struct Test;"#,
137 expect![[r#" 157 expect![[r#"
138 at Clone 158 at Default
159 at Eq
160 at Eq, PartialOrd, Ord
139 at Clone, Copy 161 at Clone, Copy
140 at Debug 162 at Debug
141 at Default 163 at Clone
142 at Hash 164 at Hash
143 at Eq
144 at PartialOrd 165 at PartialOrd
145 at Eq, PartialOrd, Ord
146 "#]], 166 "#]],
147 ) 167 )
148 } 168 }
diff --git a/crates/ide_completion/src/completions/attribute/lint.rs b/crates/ide_completion/src/completions/attribute/lint.rs
index ca99e9759..1ddc38986 100644
--- a/crates/ide_completion/src/completions/attribute/lint.rs
+++ b/crates/ide_completion/src/completions/attribute/lint.rs
@@ -33,8 +33,7 @@ pub(super) fn complete_lint(
33 33
34#[cfg(test)] 34#[cfg(test)]
35mod tests { 35mod tests {
36 36 use crate::tests::check_edit;
37 use crate::test_utils::check_edit;
38 37
39 #[test] 38 #[test]
40 fn check_empty() { 39 fn check_empty() {
diff --git a/crates/ide_completion/src/completions/attribute/repr.rs b/crates/ide_completion/src/completions/attribute/repr.rs
new file mode 100644
index 000000000..92a262a43
--- /dev/null
+++ b/crates/ide_completion/src/completions/attribute/repr.rs
@@ -0,0 +1,199 @@
1//! Completion for representations.
2
3use syntax::ast;
4
5use crate::{
6 context::CompletionContext,
7 item::{CompletionItem, CompletionItemKind, CompletionKind},
8 Completions,
9};
10
11pub(super) fn complete_repr(
12 acc: &mut Completions,
13 ctx: &CompletionContext,
14 derive_input: ast::TokenTree,
15) {
16 if let Some(existing_reprs) = super::parse_comma_sep_input(derive_input) {
17 for repr_completion in REPR_COMPLETIONS {
18 if existing_reprs
19 .iter()
20 .any(|it| repr_completion.label == it || repr_completion.collides.contains(&&**it))
21 {
22 continue;
23 }
24 let mut item = CompletionItem::new(
25 CompletionKind::Attribute,
26 ctx.source_range(),
27 repr_completion.label,
28 );
29 item.kind(CompletionItemKind::Attribute);
30 if let Some(lookup) = repr_completion.lookup {
31 item.lookup_by(lookup);
32 }
33 if let Some((snippet, cap)) = repr_completion.snippet.zip(ctx.config.snippet_cap) {
34 item.insert_snippet(cap, snippet);
35 }
36 item.add_to(acc);
37 }
38 }
39}
40
41struct ReprCompletion {
42 label: &'static str,
43 snippet: Option<&'static str>,
44 lookup: Option<&'static str>,
45 collides: &'static [&'static str],
46}
47
48const fn attr(label: &'static str, collides: &'static [&'static str]) -> ReprCompletion {
49 ReprCompletion { label, snippet: None, lookup: None, collides }
50}
51
52#[rustfmt::skip]
53const REPR_COMPLETIONS: &[ReprCompletion] = &[
54 ReprCompletion { label: "align($0)", snippet: Some("align($0)"), lookup: Some("align"), collides: &["transparent", "packed"] },
55 attr("packed", &["transparent", "align"]),
56 attr("transparent", &["C", "u8", "u16", "u32", "u64", "u128", "usize", "i8", "i16", "i32", "i64", "i128", "isize"]),
57 attr("C", &["transparent"]),
58 attr("u8", &["transparent", "u16", "u32", "u64", "u128", "usize", "i8", "i16", "i32", "i64", "i128", "isize"]),
59 attr("u16", &["transparent", "u8", "u32", "u64", "u128", "usize", "i8", "i16", "i32", "i64", "i128", "isize"]),
60 attr("u32", &["transparent", "u8", "u16", "u64", "u128", "usize", "i8", "i16", "i32", "i64", "i128", "isize"]),
61 attr("u64", &["transparent", "u8", "u16", "u32", "u128", "usize", "i8", "i16", "i32", "i64", "i128", "isize"]),
62 attr("u128", &["transparent", "u8", "u16", "u32", "u64", "usize", "i8", "i16", "i32", "i64", "i128", "isize"]),
63 attr("usize", &["transparent", "u8", "u16", "u32", "u64", "u128", "i8", "i16", "i32", "i64", "i128", "isize"]),
64 attr("i8", &["transparent", "u8", "u16", "u32", "u64", "u128", "usize", "i16", "i32", "i64", "i128", "isize"]),
65 attr("i16", &["transparent", "u8", "u16", "u32", "u64", "u128", "usize", "i8", "i32", "i64", "i128", "isize"]),
66 attr("i32", &["transparent", "u8", "u16", "u32", "u64", "u128", "usize", "i8", "i16", "i64", "i128", "isize"]),
67 attr("i64", &["transparent", "u8", "u16", "u32", "u64", "u128", "usize", "i8", "i16", "i32", "i128", "isize"]),
68 attr("i28", &["transparent", "u8", "u16", "u32", "u64", "u128", "usize", "i8", "i16", "i32", "i64", "isize"]),
69 attr("isize", &["transparent", "u8", "u16", "u32", "u64", "u128", "usize", "i8", "i16", "i32", "i64", "i128"]),
70];
71
72#[cfg(test)]
73mod tests {
74 use expect_test::{expect, Expect};
75
76 use crate::tests::completion_list;
77
78 fn check(ra_fixture: &str, expect: Expect) {
79 let actual = completion_list(ra_fixture);
80 expect.assert_eq(&actual);
81 }
82
83 #[test]
84 fn no_completion_for_incorrect_repr() {
85 check(r#"#[repr{$0)] struct Test;"#, expect![[]])
86 }
87
88 #[test]
89 fn empty() {
90 check(
91 r#"#[repr($0)] struct Test;"#,
92 expect![[r#"
93 at align($0)
94 at packed
95 at transparent
96 at C
97 at u8
98 at u16
99 at u32
100 at u64
101 at u128
102 at usize
103 at i8
104 at i16
105 at i32
106 at i64
107 at i28
108 at isize
109 "#]],
110 );
111 }
112
113 #[test]
114 fn transparent() {
115 check(r#"#[repr(transparent, $0)] struct Test;"#, expect![[r#""#]]);
116 }
117
118 #[test]
119 fn align() {
120 check(
121 r#"#[repr(align(1), $0)] struct Test;"#,
122 expect![[r#"
123 at align($0)
124 at transparent
125 at C
126 at u8
127 at u16
128 at u32
129 at u64
130 at u128
131 at usize
132 at i8
133 at i16
134 at i32
135 at i64
136 at i28
137 at isize
138 "#]],
139 );
140 }
141
142 #[test]
143 fn packed() {
144 check(
145 r#"#[repr(packed, $0)] struct Test;"#,
146 expect![[r#"
147 at transparent
148 at C
149 at u8
150 at u16
151 at u32
152 at u64
153 at u128
154 at usize
155 at i8
156 at i16
157 at i32
158 at i64
159 at i28
160 at isize
161 "#]],
162 );
163 }
164
165 #[test]
166 fn c() {
167 check(
168 r#"#[repr(C, $0)] struct Test;"#,
169 expect![[r#"
170 at align($0)
171 at packed
172 at u8
173 at u16
174 at u32
175 at u64
176 at u128
177 at usize
178 at i8
179 at i16
180 at i32
181 at i64
182 at i28
183 at isize
184 "#]],
185 );
186 }
187
188 #[test]
189 fn prim() {
190 check(
191 r#"#[repr(usize, $0)] struct Test;"#,
192 expect![[r#"
193 at align($0)
194 at packed
195 at C
196 "#]],
197 );
198 }
199}