aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_completion/src')
-rw-r--r--crates/ide_completion/src/completions/attribute.rs26
-rw-r--r--crates/ide_completion/src/completions/attribute/derive.rs38
-rw-r--r--crates/ide_completion/src/completions/attribute/lint.rs33
3 files changed, 67 insertions, 30 deletions
diff --git a/crates/ide_completion/src/completions/attribute.rs b/crates/ide_completion/src/completions/attribute.rs
index 610fec65a..13d5b90c9 100644
--- a/crates/ide_completion/src/completions/attribute.rs
+++ b/crates/ide_completion/src/completions/attribute.rs
@@ -3,8 +3,6 @@
3//! This module uses a bit of static metadata to provide completions 3//! This module uses a bit of static metadata to provide completions
4//! for built-in attributes. 4//! for built-in attributes.
5 5
6use std::mem;
7
8use once_cell::sync::Lazy; 6use once_cell::sync::Lazy;
9use rustc_hash::{FxHashMap, FxHashSet}; 7use rustc_hash::{FxHashMap, FxHashSet};
10use syntax::{ast, AstNode, NodeOrToken, SyntaxKind, T}; 8use syntax::{ast, AstNode, NodeOrToken, SyntaxKind, T};
@@ -272,27 +270,27 @@ const ATTRIBUTES: &[AttrCompletion] = &[
272fn parse_comma_sep_input(derive_input: ast::TokenTree) -> Option<FxHashSet<String>> { 270fn parse_comma_sep_input(derive_input: ast::TokenTree) -> Option<FxHashSet<String>> {
273 let (l_paren, r_paren) = derive_input.l_paren_token().zip(derive_input.r_paren_token())?; 271 let (l_paren, r_paren) = derive_input.l_paren_token().zip(derive_input.r_paren_token())?;
274 let mut input_derives = FxHashSet::default(); 272 let mut input_derives = FxHashSet::default();
275 let mut current_derive = String::new(); 273 let mut tokens = derive_input
276 for token in derive_input
277 .syntax() 274 .syntax()
278 .children_with_tokens() 275 .children_with_tokens()
279 .filter_map(NodeOrToken::into_token) 276 .filter_map(NodeOrToken::into_token)
280 .skip_while(|token| token != &l_paren) 277 .skip_while(|token| token != &l_paren)
281 .skip(1) 278 .skip(1)
282 .take_while(|token| token != &r_paren) 279 .take_while(|token| token != &r_paren)
283 { 280 .peekable();
284 if token.kind() == T![,] { 281 let mut input = String::new();
285 if !current_derive.is_empty() { 282 while tokens.peek().is_some() {
286 input_derives.insert(mem::take(&mut current_derive)); 283 for token in tokens.by_ref().take_while(|t| t.kind() != T![,]) {
287 } 284 input.push_str(token.text());
288 } else {
289 current_derive.push_str(token.text().trim());
290 } 285 }
291 }
292 286
293 if !current_derive.is_empty() { 287 if !input.is_empty() {
294 input_derives.insert(current_derive); 288 input_derives.insert(input.trim().to_owned());
289 }
290
291 input.clear();
295 } 292 }
293
296 Some(input_derives) 294 Some(input_derives)
297} 295}
298 296
diff --git a/crates/ide_completion/src/completions/attribute/derive.rs b/crates/ide_completion/src/completions/attribute/derive.rs
index 7b0a778a2..634c0cb00 100644
--- a/crates/ide_completion/src/completions/attribute/derive.rs
+++ b/crates/ide_completion/src/completions/attribute/derive.rs
@@ -45,6 +45,7 @@ pub(super) fn complete_derive(
45 } 45 }
46 } 46 }
47} 47}
48
48fn get_derive_names_in_scope(ctx: &CompletionContext) -> FxHashSet<String> { 49fn get_derive_names_in_scope(ctx: &CompletionContext) -> FxHashSet<String> {
49 let mut result = FxHashSet::default(); 50 let mut result = FxHashSet::default();
50 ctx.scope.process_all_names(&mut |name, scope_def| { 51 ctx.scope.process_all_names(&mut |name, scope_def| {
@@ -89,12 +90,14 @@ mod tests {
89 } 90 }
90 91
91 #[test] 92 #[test]
92 fn empty_derive_completion() { 93 fn no_completion_for_incorrect_derive() {
94 check(r#"#[derive{$0)] struct Test;"#, expect![[]])
95 }
96
97 #[test]
98 fn empty_derive() {
93 check( 99 check(
94 r#" 100 r#"#[derive($0)] struct Test;"#,
95#[derive($0)]
96struct Test {}
97 "#,
98 expect![[r#" 101 expect![[r#"
99 at Clone 102 at Clone
100 at Clone, Copy 103 at Clone, Copy
@@ -110,23 +113,26 @@ struct Test {}
110 } 113 }
111 114
112 #[test] 115 #[test]
113 fn no_completion_for_incorrect_derive() { 116 fn derive_with_input() {
114 check( 117 check(
115 r#" 118 r#"#[derive(serde::Serialize, PartialEq, $0)] struct Test;"#,
116#[derive{$0)] 119 expect![[r#"
117struct Test {} 120 at Clone
118"#, 121 at Clone, Copy
119 expect![[r#""#]], 122 at Debug
123 at Default
124 at Hash
125 at Eq
126 at PartialOrd
127 at Eq, PartialOrd, Ord
128 "#]],
120 ) 129 )
121 } 130 }
122 131
123 #[test] 132 #[test]
124 fn derive_with_input_completion() { 133 fn derive_with_input2() {
125 check( 134 check(
126 r#" 135 r#"#[derive($0 serde::Serialize, PartialEq)] struct Test;"#,
127#[derive(serde::Serialize, PartialEq, $0)]
128struct Test {}
129"#,
130 expect![[r#" 136 expect![[r#"
131 at Clone 137 at Clone
132 at Clone, Copy 138 at Clone, Copy
diff --git a/crates/ide_completion/src/completions/attribute/lint.rs b/crates/ide_completion/src/completions/attribute/lint.rs
index 115c6cfe0..403630dce 100644
--- a/crates/ide_completion/src/completions/attribute/lint.rs
+++ b/crates/ide_completion/src/completions/attribute/lint.rs
@@ -152,3 +152,36 @@ pub(super) const DEFAULT_LINT_COMPLETIONS: &[LintCompletion] = &[
152 LintCompletion { label: "unconditional_panic", description: r#"operation will cause a panic at runtime"# }, 152 LintCompletion { label: "unconditional_panic", description: r#"operation will cause a panic at runtime"# },
153 LintCompletion { label: "unknown_crate_types", description: r#"unknown crate type found in `#[crate_type]` directive"# }, 153 LintCompletion { label: "unknown_crate_types", description: r#"unknown crate type found in `#[crate_type]` directive"# },
154]; 154];
155
156#[cfg(test)]
157mod tests {
158
159 use crate::test_utils::check_edit;
160
161 #[test]
162 fn check_empty() {
163 check_edit(
164 "deprecated",
165 r#"#[allow($0)] struct Test;"#,
166 r#"#[allow(deprecated)] struct Test;"#,
167 )
168 }
169
170 #[test]
171 fn check_with_existing() {
172 check_edit(
173 "deprecated",
174 r#"#[allow(keyword_idents, $0)] struct Test;"#,
175 r#"#[allow(keyword_idents, deprecated)] struct Test;"#,
176 )
177 }
178
179 #[test]
180 fn check_qualified() {
181 check_edit(
182 "deprecated",
183 r#"#[allow(keyword_idents, $0)] struct Test;"#,
184 r#"#[allow(keyword_idents, deprecated)] struct Test;"#,
185 )
186 }
187}