aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/completion/complete_attribute.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/completion/complete_attribute.rs')
-rw-r--r--crates/ra_ide/src/completion/complete_attribute.rs654
1 files changed, 0 insertions, 654 deletions
diff --git a/crates/ra_ide/src/completion/complete_attribute.rs b/crates/ra_ide/src/completion/complete_attribute.rs
deleted file mode 100644
index f2782d4b9..000000000
--- a/crates/ra_ide/src/completion/complete_attribute.rs
+++ /dev/null
@@ -1,654 +0,0 @@
1//! Completion for attributes
2//!
3//! This module uses a bit of static metadata to provide completions
4//! for built-in attributes.
5
6use ra_syntax::{ast, AstNode, SyntaxKind};
7use rustc_hash::FxHashSet;
8
9use crate::completion::{
10 completion_context::CompletionContext,
11 completion_item::{CompletionItem, CompletionItemKind, CompletionKind, Completions},
12};
13
14use crate::completion::UNSTABLE_FEATURE_DESCRIPTOR;
15
16pub(super) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
17 let attribute = ctx.attribute_under_caret.as_ref()?;
18 match (attribute.path(), attribute.token_tree()) {
19 (Some(path), Some(token_tree)) if path.to_string() == "derive" => {
20 complete_derive(acc, ctx, token_tree)
21 }
22 (Some(path), Some(token_tree)) if path.to_string() == "feature" => {
23 complete_lint(acc, ctx, token_tree, UNSTABLE_FEATURE_DESCRIPTOR);
24 }
25 (Some(path), Some(token_tree))
26 if ["allow", "warn", "deny", "forbid"]
27 .iter()
28 .any(|lint_level| lint_level == &path.to_string()) =>
29 {
30 complete_lint(acc, ctx, token_tree, DEFAULT_LINT_COMPLETIONS)
31 }
32 (_, Some(_token_tree)) => {}
33 _ => complete_attribute_start(acc, ctx, attribute),
34 }
35 Some(())
36}
37
38fn complete_attribute_start(acc: &mut Completions, ctx: &CompletionContext, attribute: &ast::Attr) {
39 for attr_completion in ATTRIBUTES {
40 let mut item = CompletionItem::new(
41 CompletionKind::Attribute,
42 ctx.source_range(),
43 attr_completion.label,
44 )
45 .kind(CompletionItemKind::Attribute);
46
47 if let Some(lookup) = attr_completion.lookup {
48 item = item.lookup_by(lookup);
49 }
50
51 match (attr_completion.snippet, ctx.config.snippet_cap) {
52 (Some(snippet), Some(cap)) => {
53 item = item.insert_snippet(cap, snippet);
54 }
55 _ => {}
56 }
57
58 if attribute.kind() == ast::AttrKind::Inner || !attr_completion.prefer_inner {
59 acc.add(item);
60 }
61 }
62}
63
64struct AttrCompletion {
65 label: &'static str,
66 lookup: Option<&'static str>,
67 snippet: Option<&'static str>,
68 prefer_inner: bool,
69}
70
71impl AttrCompletion {
72 const fn prefer_inner(self) -> AttrCompletion {
73 AttrCompletion { prefer_inner: true, ..self }
74 }
75}
76
77const fn attr(
78 label: &'static str,
79 lookup: Option<&'static str>,
80 snippet: Option<&'static str>,
81) -> AttrCompletion {
82 AttrCompletion { label, lookup, snippet, prefer_inner: false }
83}
84
85const ATTRIBUTES: &[AttrCompletion] = &[
86 attr("allow(…)", Some("allow"), Some("allow(${0:lint})")),
87 attr("cfg_attr(…)", Some("cfg_attr"), Some("cfg_attr(${1:predicate}, ${0:attr})")),
88 attr("cfg(…)", Some("cfg"), Some("cfg(${0:predicate})")),
89 attr("deny(…)", Some("deny"), Some("deny(${0:lint})")),
90 attr(r#"deprecated = "…""#, Some("deprecated"), Some(r#"deprecated = "${0:reason}""#)),
91 attr("derive(…)", Some("derive"), Some(r#"derive(${0:Debug})"#)),
92 attr(r#"doc = "…""#, Some("doc"), Some(r#"doc = "${0:docs}""#)),
93 attr("feature(…)", Some("feature"), Some("feature(${0:lint})")).prefer_inner(),
94 attr("forbid(…)", Some("forbid"), Some("forbid(${0:lint})")),
95 // FIXME: resolve through macro resolution?
96 attr("global_allocator", None, None).prefer_inner(),
97 attr(r#"ignore = "…""#, Some("ignore"), Some(r#"ignore = "${0:reason}""#)),
98 attr("inline(…)", Some("inline"), Some("inline(${0:lint})")),
99 attr(r#"link_name = "…""#, Some("link_name"), Some(r#"link_name = "${0:symbol_name}""#)),
100 attr("link", None, None),
101 attr("macro_export", None, None),
102 attr("macro_use", None, None),
103 attr(r#"must_use = "…""#, Some("must_use"), Some(r#"must_use = "${0:reason}""#)),
104 attr("no_mangle", None, None),
105 attr("no_std", None, None).prefer_inner(),
106 attr("non_exhaustive", None, None),
107 attr("panic_handler", None, None).prefer_inner(),
108 attr("path = \"…\"", Some("path"), Some("path =\"${0:path}\"")),
109 attr("proc_macro", None, None),
110 attr("proc_macro_attribute", None, None),
111 attr("proc_macro_derive(…)", Some("proc_macro_derive"), Some("proc_macro_derive(${0:Trait})")),
112 attr("recursion_limit = …", Some("recursion_limit"), Some("recursion_limit = ${0:128}"))
113 .prefer_inner(),
114 attr("repr(…)", Some("repr"), Some("repr(${0:C})")),
115 attr(
116 "should_panic(…)",
117 Some("should_panic"),
118 Some(r#"should_panic(expected = "${0:reason}")"#),
119 ),
120 attr(
121 r#"target_feature = "…""#,
122 Some("target_feature"),
123 Some("target_feature = \"${0:feature}\""),
124 ),
125 attr("test", None, None),
126 attr("used", None, None),
127 attr("warn(…)", Some("warn"), Some("warn(${0:lint})")),
128 attr(
129 r#"windows_subsystem = "…""#,
130 Some("windows_subsystem"),
131 Some(r#"windows_subsystem = "${0:subsystem}""#),
132 )
133 .prefer_inner(),
134];
135
136fn complete_derive(acc: &mut Completions, ctx: &CompletionContext, derive_input: ast::TokenTree) {
137 if let Ok(existing_derives) = parse_comma_sep_input(derive_input) {
138 for derive_completion in DEFAULT_DERIVE_COMPLETIONS
139 .into_iter()
140 .filter(|completion| !existing_derives.contains(completion.label))
141 {
142 let mut label = derive_completion.label.to_owned();
143 for dependency in derive_completion
144 .dependencies
145 .into_iter()
146 .filter(|&&dependency| !existing_derives.contains(dependency))
147 {
148 label.push_str(", ");
149 label.push_str(dependency);
150 }
151 acc.add(
152 CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), label)
153 .kind(CompletionItemKind::Attribute),
154 );
155 }
156
157 for custom_derive_name in get_derive_names_in_scope(ctx).difference(&existing_derives) {
158 acc.add(
159 CompletionItem::new(
160 CompletionKind::Attribute,
161 ctx.source_range(),
162 custom_derive_name,
163 )
164 .kind(CompletionItemKind::Attribute),
165 );
166 }
167 }
168}
169
170fn complete_lint(
171 acc: &mut Completions,
172 ctx: &CompletionContext,
173 derive_input: ast::TokenTree,
174 lints_completions: &[LintCompletion],
175) {
176 if let Ok(existing_lints) = parse_comma_sep_input(derive_input) {
177 for lint_completion in lints_completions
178 .into_iter()
179 .filter(|completion| !existing_lints.contains(completion.label))
180 {
181 acc.add(
182 CompletionItem::new(
183 CompletionKind::Attribute,
184 ctx.source_range(),
185 lint_completion.label,
186 )
187 .kind(CompletionItemKind::Attribute)
188 .detail(lint_completion.description),
189 );
190 }
191 }
192}
193
194fn parse_comma_sep_input(derive_input: ast::TokenTree) -> Result<FxHashSet<String>, ()> {
195 match (derive_input.left_delimiter_token(), derive_input.right_delimiter_token()) {
196 (Some(left_paren), Some(right_paren))
197 if left_paren.kind() == SyntaxKind::L_PAREN
198 && right_paren.kind() == SyntaxKind::R_PAREN =>
199 {
200 let mut input_derives = FxHashSet::default();
201 let mut current_derive = String::new();
202 for token in derive_input
203 .syntax()
204 .children_with_tokens()
205 .filter_map(|token| token.into_token())
206 .skip_while(|token| token != &left_paren)
207 .skip(1)
208 .take_while(|token| token != &right_paren)
209 {
210 if SyntaxKind::COMMA == token.kind() {
211 if !current_derive.is_empty() {
212 input_derives.insert(current_derive);
213 current_derive = String::new();
214 }
215 } else {
216 current_derive.push_str(token.to_string().trim());
217 }
218 }
219
220 if !current_derive.is_empty() {
221 input_derives.insert(current_derive);
222 }
223 Ok(input_derives)
224 }
225 _ => Err(()),
226 }
227}
228
229fn get_derive_names_in_scope(ctx: &CompletionContext) -> FxHashSet<String> {
230 let mut result = FxHashSet::default();
231 ctx.scope.process_all_names(&mut |name, scope_def| {
232 if let hir::ScopeDef::MacroDef(mac) = scope_def {
233 if mac.is_derive_macro() {
234 result.insert(name.to_string());
235 }
236 }
237 });
238 result
239}
240
241struct DeriveCompletion {
242 label: &'static str,
243 dependencies: &'static [&'static str],
244}
245
246/// Standard Rust derives and the information about their dependencies
247/// (the dependencies are needed so that the main derive don't break the compilation when added)
248#[rustfmt::skip]
249const DEFAULT_DERIVE_COMPLETIONS: &[DeriveCompletion] = &[
250 DeriveCompletion { label: "Clone", dependencies: &[] },
251 DeriveCompletion { label: "Copy", dependencies: &["Clone"] },
252 DeriveCompletion { label: "Debug", dependencies: &[] },
253 DeriveCompletion { label: "Default", dependencies: &[] },
254 DeriveCompletion { label: "Hash", dependencies: &[] },
255 DeriveCompletion { label: "PartialEq", dependencies: &[] },
256 DeriveCompletion { label: "Eq", dependencies: &["PartialEq"] },
257 DeriveCompletion { label: "PartialOrd", dependencies: &["PartialEq"] },
258 DeriveCompletion { label: "Ord", dependencies: &["PartialOrd", "Eq", "PartialEq"] },
259];
260
261pub(crate) struct LintCompletion {
262 pub label: &'static str,
263 pub description: &'static str,
264}
265
266#[rustfmt::skip]
267const DEFAULT_LINT_COMPLETIONS: &[LintCompletion] = &[
268 LintCompletion { label: "absolute_paths_not_starting_with_crate", description: r#"fully qualified paths that start with a module name instead of `crate`, `self`, or an extern crate name"# },
269 LintCompletion { label: "anonymous_parameters", description: r#"detects anonymous parameters"# },
270 LintCompletion { label: "box_pointers", description: r#"use of owned (Box type) heap memory"# },
271 LintCompletion { label: "deprecated_in_future", description: r#"detects use of items that will be deprecated in a future version"# },
272 LintCompletion { label: "elided_lifetimes_in_paths", description: r#"hidden lifetime parameters in types are deprecated"# },
273 LintCompletion { label: "explicit_outlives_requirements", description: r#"outlives requirements can be inferred"# },
274 LintCompletion { label: "indirect_structural_match", description: r#"pattern with const indirectly referencing non-structural-match type"# },
275 LintCompletion { label: "keyword_idents", description: r#"detects edition keywords being used as an identifier"# },
276 LintCompletion { label: "macro_use_extern_crate", description: r#"the `#[macro_use]` attribute is now deprecated in favor of using macros via the module system"# },
277 LintCompletion { label: "meta_variable_misuse", description: r#"possible meta-variable misuse at macro definition"# },
278 LintCompletion { label: "missing_copy_implementations", description: r#"detects potentially-forgotten implementations of `Copy`"# },
279 LintCompletion { label: "missing_crate_level_docs", description: r#"detects crates with no crate-level documentation"# },
280 LintCompletion { label: "missing_debug_implementations", description: r#"detects missing implementations of Debug"# },
281 LintCompletion { label: "missing_docs", description: r#"detects missing documentation for public members"# },
282 LintCompletion { label: "missing_doc_code_examples", description: r#"detects publicly-exported items without code samples in their documentation"# },
283 LintCompletion { label: "non_ascii_idents", description: r#"detects non-ASCII identifiers"# },
284 LintCompletion { label: "private_doc_tests", description: r#"detects code samples in docs of private items not documented by rustdoc"# },
285 LintCompletion { label: "single_use_lifetimes", description: r#"detects lifetime parameters that are only used once"# },
286 LintCompletion { label: "trivial_casts", description: r#"detects trivial casts which could be removed"# },
287 LintCompletion { label: "trivial_numeric_casts", description: r#"detects trivial casts of numeric types which could be removed"# },
288 LintCompletion { label: "unaligned_references", description: r#"detects unaligned references to fields of packed structs"# },
289 LintCompletion { label: "unreachable_pub", description: r#"`pub` items not reachable from crate root"# },
290 LintCompletion { label: "unsafe_code", description: r#"usage of `unsafe` code"# },
291 LintCompletion { label: "unsafe_op_in_unsafe_fn", description: r#"unsafe operations in unsafe functions without an explicit unsafe block are deprecated"# },
292 LintCompletion { label: "unstable_features", description: r#"enabling unstable features (deprecated. do not use)"# },
293 LintCompletion { label: "unused_crate_dependencies", description: r#"crate dependencies that are never used"# },
294 LintCompletion { label: "unused_extern_crates", description: r#"extern crates that are never used"# },
295 LintCompletion { label: "unused_import_braces", description: r#"unnecessary braces around an imported item"# },
296 LintCompletion { label: "unused_lifetimes", description: r#"detects lifetime parameters that are never used"# },
297 LintCompletion { label: "unused_qualifications", description: r#"detects unnecessarily qualified names"# },
298 LintCompletion { label: "unused_results", description: r#"unused result of an expression in a statement"# },
299 LintCompletion { label: "variant_size_differences", description: r#"detects enums with widely varying variant sizes"# },
300 LintCompletion { label: "array_into_iter", description: r#"detects calling `into_iter` on arrays"# },
301 LintCompletion { label: "asm_sub_register", description: r#"using only a subset of a register for inline asm inputs"# },
302 LintCompletion { label: "bare_trait_objects", description: r#"suggest using `dyn Trait` for trait objects"# },
303 LintCompletion { label: "bindings_with_variant_name", description: r#"detects pattern bindings with the same name as one of the matched variants"# },
304 LintCompletion { label: "cenum_impl_drop_cast", description: r#"a C-like enum implementing Drop is cast"# },
305 LintCompletion { label: "clashing_extern_declarations", description: r#"detects when an extern fn has been declared with the same name but different types"# },
306 LintCompletion { label: "coherence_leak_check", description: r#"distinct impls distinguished only by the leak-check code"# },
307 LintCompletion { label: "confusable_idents", description: r#"detects visually confusable pairs between identifiers"# },
308 LintCompletion { label: "dead_code", description: r#"detect unused, unexported items"# },
309 LintCompletion { label: "deprecated", description: r#"detects use of deprecated items"# },
310 LintCompletion { label: "ellipsis_inclusive_range_patterns", description: r#"`...` range patterns are deprecated"# },
311 LintCompletion { label: "exported_private_dependencies", description: r#"public interface leaks type from a private dependency"# },
312 LintCompletion { label: "illegal_floating_point_literal_pattern", description: r#"floating-point literals cannot be used in patterns"# },
313 LintCompletion { label: "improper_ctypes", description: r#"proper use of libc types in foreign modules"# },
314 LintCompletion { label: "improper_ctypes_definitions", description: r#"proper use of libc types in foreign item definitions"# },
315 LintCompletion { label: "incomplete_features", description: r#"incomplete features that may function improperly in some or all cases"# },
316 LintCompletion { label: "inline_no_sanitize", description: r#"detects incompatible use of `#[inline(always)]` and `#[no_sanitize(...)]`"# },
317 LintCompletion { label: "intra_doc_link_resolution_failure", description: r#"failures in resolving intra-doc link targets"# },
318 LintCompletion { label: "invalid_codeblock_attributes", description: r#"codeblock attribute looks a lot like a known one"# },
319 LintCompletion { label: "invalid_value", description: r#"an invalid value is being created (such as a NULL reference)"# },
320 LintCompletion { label: "irrefutable_let_patterns", description: r#"detects irrefutable patterns in if-let and while-let statements"# },
321 LintCompletion { label: "late_bound_lifetime_arguments", description: r#"detects generic lifetime arguments in path segments with late bound lifetime parameters"# },
322 LintCompletion { label: "mixed_script_confusables", description: r#"detects Unicode scripts whose mixed script confusables codepoints are solely used"# },
323 LintCompletion { label: "mutable_borrow_reservation_conflict", description: r#"reservation of a two-phased borrow conflicts with other shared borrows"# },
324 LintCompletion { label: "non_camel_case_types", description: r#"types, variants, traits and type parameters should have camel case names"# },
325 LintCompletion { label: "non_shorthand_field_patterns", description: r#"using `Struct { x: x }` instead of `Struct { x }` in a pattern"# },
326 LintCompletion { label: "non_snake_case", description: r#"variables, methods, functions, lifetime parameters and modules should have snake case names"# },
327 LintCompletion { label: "non_upper_case_globals", description: r#"static constants should have uppercase identifiers"# },
328 LintCompletion { label: "no_mangle_generic_items", description: r#"generic items must be mangled"# },
329 LintCompletion { label: "overlapping_patterns", description: r#"detects overlapping patterns"# },
330 LintCompletion { label: "path_statements", description: r#"path statements with no effect"# },
331 LintCompletion { label: "private_in_public", description: r#"detect private items in public interfaces not caught by the old implementation"# },
332 LintCompletion { label: "proc_macro_derive_resolution_fallback", description: r#"detects proc macro derives using inaccessible names from parent modules"# },
333 LintCompletion { label: "redundant_semicolons", description: r#"detects unnecessary trailing semicolons"# },
334 LintCompletion { label: "renamed_and_removed_lints", description: r#"lints that have been renamed or removed"# },
335 LintCompletion { label: "safe_packed_borrows", description: r#"safe borrows of fields of packed structs were erroneously allowed"# },
336 LintCompletion { label: "stable_features", description: r#"stable features found in `#[feature]` directive"# },
337 LintCompletion { label: "trivial_bounds", description: r#"these bounds don't depend on an type parameters"# },
338 LintCompletion { label: "type_alias_bounds", description: r#"bounds in type aliases are not enforced"# },
339 LintCompletion { label: "tyvar_behind_raw_pointer", description: r#"raw pointer to an inference variable"# },
340 LintCompletion { label: "uncommon_codepoints", description: r#"detects uncommon Unicode codepoints in identifiers"# },
341 LintCompletion { label: "unconditional_recursion", description: r#"functions that cannot return without calling themselves"# },
342 LintCompletion { label: "unknown_lints", description: r#"unrecognized lint attribute"# },
343 LintCompletion { label: "unnameable_test_items", description: r#"detects an item that cannot be named being marked as `#[test_case]`"# },
344 LintCompletion { label: "unreachable_code", description: r#"detects unreachable code paths"# },
345 LintCompletion { label: "unreachable_patterns", description: r#"detects unreachable patterns"# },
346 LintCompletion { label: "unstable_name_collisions", description: r#"detects name collision with an existing but unstable method"# },
347 LintCompletion { label: "unused_allocation", description: r#"detects unnecessary allocations that can be eliminated"# },
348 LintCompletion { label: "unused_assignments", description: r#"detect assignments that will never be read"# },
349 LintCompletion { label: "unused_attributes", description: r#"detects attributes that were not used by the compiler"# },
350 LintCompletion { label: "unused_braces", description: r#"unnecessary braces around an expression"# },
351 LintCompletion { label: "unused_comparisons", description: r#"comparisons made useless by limits of the types involved"# },
352 LintCompletion { label: "unused_doc_comments", description: r#"detects doc comments that aren't used by rustdoc"# },
353 LintCompletion { label: "unused_features", description: r#"unused features found in crate-level `#[feature]` directives"# },
354 LintCompletion { label: "unused_imports", description: r#"imports that are never used"# },
355 LintCompletion { label: "unused_labels", description: r#"detects labels that are never used"# },
356 LintCompletion { label: "unused_macros", description: r#"detects macros that were not used"# },
357 LintCompletion { label: "unused_must_use", description: r#"unused result of a type flagged as `#[must_use]`"# },
358 LintCompletion { label: "unused_mut", description: r#"detect mut variables which don't need to be mutable"# },
359 LintCompletion { label: "unused_parens", description: r#"`if`, `match`, `while` and `return` do not need parentheses"# },
360 LintCompletion { label: "unused_unsafe", description: r#"unnecessary use of an `unsafe` block"# },
361 LintCompletion { label: "unused_variables", description: r#"detect variables which are not used in any way"# },
362 LintCompletion { label: "warnings", description: r#"mass-change the level for lints which produce warnings"# },
363 LintCompletion { label: "where_clauses_object_safety", description: r#"checks the object safety of where clauses"# },
364 LintCompletion { label: "while_true", description: r#"suggest using `loop { }` instead of `while true { }`"# },
365 LintCompletion { label: "ambiguous_associated_items", description: r#"ambiguous associated items"# },
366 LintCompletion { label: "arithmetic_overflow", description: r#"arithmetic operation overflows"# },
367 LintCompletion { label: "conflicting_repr_hints", description: r#"conflicts between `#[repr(..)]` hints that were previously accepted and used in practice"# },
368 LintCompletion { label: "const_err", description: r#"constant evaluation detected erroneous expression"# },
369 LintCompletion { label: "ill_formed_attribute_input", description: r#"ill-formed attribute inputs that were previously accepted and used in practice"# },
370 LintCompletion { label: "incomplete_include", description: r#"trailing content in included file"# },
371 LintCompletion { label: "invalid_type_param_default", description: r#"type parameter default erroneously allowed in invalid location"# },
372 LintCompletion { label: "macro_expanded_macro_exports_accessed_by_absolute_paths", description: r#"macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths"# },
373 LintCompletion { label: "missing_fragment_specifier", description: r#"detects missing fragment specifiers in unused `macro_rules!` patterns"# },
374 LintCompletion { label: "mutable_transmutes", description: r#"mutating transmuted &mut T from &T may cause undefined behavior"# },
375 LintCompletion { label: "no_mangle_const_items", description: r#"const items will not have their symbols exported"# },
376 LintCompletion { label: "order_dependent_trait_objects", description: r#"trait-object types were treated as different depending on marker-trait order"# },
377 LintCompletion { label: "overflowing_literals", description: r#"literal out of range for its type"# },
378 LintCompletion { label: "patterns_in_fns_without_body", description: r#"patterns in functions without body were erroneously allowed"# },
379 LintCompletion { label: "pub_use_of_private_extern_crate", description: r#"detect public re-exports of private extern crates"# },
380 LintCompletion { label: "soft_unstable", description: r#"a feature gate that doesn't break dependent crates"# },
381 LintCompletion { label: "unconditional_panic", description: r#"operation will cause a panic at runtime"# },
382 LintCompletion { label: "unknown_crate_types", description: r#"unknown crate type found in `#[crate_type]` directive"# },
383];
384
385#[cfg(test)]
386mod tests {
387 use expect::{expect, Expect};
388
389 use crate::completion::{test_utils::completion_list, CompletionKind};
390
391 fn check(ra_fixture: &str, expect: Expect) {
392 let actual = completion_list(ra_fixture, CompletionKind::Attribute);
393 expect.assert_eq(&actual);
394 }
395
396 #[test]
397 fn empty_derive_completion() {
398 check(
399 r#"
400#[derive(<|>)]
401struct Test {}
402 "#,
403 expect![[r#"
404 at Clone
405 at Copy, Clone
406 at Debug
407 at Default
408 at Eq, PartialEq
409 at Hash
410 at Ord, PartialOrd, Eq, PartialEq
411 at PartialEq
412 at PartialOrd, PartialEq
413 "#]],
414 );
415 }
416
417 #[test]
418 fn empty_lint_completion() {
419 check(
420 r#"#[allow(<|>)]"#,
421 expect![[r#"
422 at absolute_paths_not_starting_with_crate fully qualified paths that start with a module name instead of `crate`, `self`, or an extern crate name
423 at ambiguous_associated_items ambiguous associated items
424 at anonymous_parameters detects anonymous parameters
425 at arithmetic_overflow arithmetic operation overflows
426 at array_into_iter detects calling `into_iter` on arrays
427 at asm_sub_register using only a subset of a register for inline asm inputs
428 at bare_trait_objects suggest using `dyn Trait` for trait objects
429 at bindings_with_variant_name detects pattern bindings with the same name as one of the matched variants
430 at box_pointers use of owned (Box type) heap memory
431 at cenum_impl_drop_cast a C-like enum implementing Drop is cast
432 at clashing_extern_declarations detects when an extern fn has been declared with the same name but different types
433 at coherence_leak_check distinct impls distinguished only by the leak-check code
434 at conflicting_repr_hints conflicts between `#[repr(..)]` hints that were previously accepted and used in practice
435 at confusable_idents detects visually confusable pairs between identifiers
436 at const_err constant evaluation detected erroneous expression
437 at dead_code detect unused, unexported items
438 at deprecated detects use of deprecated items
439 at deprecated_in_future detects use of items that will be deprecated in a future version
440 at elided_lifetimes_in_paths hidden lifetime parameters in types are deprecated
441 at ellipsis_inclusive_range_patterns `...` range patterns are deprecated
442 at explicit_outlives_requirements outlives requirements can be inferred
443 at exported_private_dependencies public interface leaks type from a private dependency
444 at ill_formed_attribute_input ill-formed attribute inputs that were previously accepted and used in practice
445 at illegal_floating_point_literal_pattern floating-point literals cannot be used in patterns
446 at improper_ctypes proper use of libc types in foreign modules
447 at improper_ctypes_definitions proper use of libc types in foreign item definitions
448 at incomplete_features incomplete features that may function improperly in some or all cases
449 at incomplete_include trailing content in included file
450 at indirect_structural_match pattern with const indirectly referencing non-structural-match type
451 at inline_no_sanitize detects incompatible use of `#[inline(always)]` and `#[no_sanitize(...)]`
452 at intra_doc_link_resolution_failure failures in resolving intra-doc link targets
453 at invalid_codeblock_attributes codeblock attribute looks a lot like a known one
454 at invalid_type_param_default type parameter default erroneously allowed in invalid location
455 at invalid_value an invalid value is being created (such as a NULL reference)
456 at irrefutable_let_patterns detects irrefutable patterns in if-let and while-let statements
457 at keyword_idents detects edition keywords being used as an identifier
458 at late_bound_lifetime_arguments detects generic lifetime arguments in path segments with late bound lifetime parameters
459 at macro_expanded_macro_exports_accessed_by_absolute_paths macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths
460 at macro_use_extern_crate the `#[macro_use]` attribute is now deprecated in favor of using macros via the module system
461 at meta_variable_misuse possible meta-variable misuse at macro definition
462 at missing_copy_implementations detects potentially-forgotten implementations of `Copy`
463 at missing_crate_level_docs detects crates with no crate-level documentation
464 at missing_debug_implementations detects missing implementations of Debug
465 at missing_doc_code_examples detects publicly-exported items without code samples in their documentation
466 at missing_docs detects missing documentation for public members
467 at missing_fragment_specifier detects missing fragment specifiers in unused `macro_rules!` patterns
468 at mixed_script_confusables detects Unicode scripts whose mixed script confusables codepoints are solely used
469 at mutable_borrow_reservation_conflict reservation of a two-phased borrow conflicts with other shared borrows
470 at mutable_transmutes mutating transmuted &mut T from &T may cause undefined behavior
471 at no_mangle_const_items const items will not have their symbols exported
472 at no_mangle_generic_items generic items must be mangled
473 at non_ascii_idents detects non-ASCII identifiers
474 at non_camel_case_types types, variants, traits and type parameters should have camel case names
475 at non_shorthand_field_patterns using `Struct { x: x }` instead of `Struct { x }` in a pattern
476 at non_snake_case variables, methods, functions, lifetime parameters and modules should have snake case names
477 at non_upper_case_globals static constants should have uppercase identifiers
478 at order_dependent_trait_objects trait-object types were treated as different depending on marker-trait order
479 at overflowing_literals literal out of range for its type
480 at overlapping_patterns detects overlapping patterns
481 at path_statements path statements with no effect
482 at patterns_in_fns_without_body patterns in functions without body were erroneously allowed
483 at private_doc_tests detects code samples in docs of private items not documented by rustdoc
484 at private_in_public detect private items in public interfaces not caught by the old implementation
485 at proc_macro_derive_resolution_fallback detects proc macro derives using inaccessible names from parent modules
486 at pub_use_of_private_extern_crate detect public re-exports of private extern crates
487 at redundant_semicolons detects unnecessary trailing semicolons
488 at renamed_and_removed_lints lints that have been renamed or removed
489 at safe_packed_borrows safe borrows of fields of packed structs were erroneously allowed
490 at single_use_lifetimes detects lifetime parameters that are only used once
491 at soft_unstable a feature gate that doesn't break dependent crates
492 at stable_features stable features found in `#[feature]` directive
493 at trivial_bounds these bounds don't depend on an type parameters
494 at trivial_casts detects trivial casts which could be removed
495 at trivial_numeric_casts detects trivial casts of numeric types which could be removed
496 at type_alias_bounds bounds in type aliases are not enforced
497 at tyvar_behind_raw_pointer raw pointer to an inference variable
498 at unaligned_references detects unaligned references to fields of packed structs
499 at uncommon_codepoints detects uncommon Unicode codepoints in identifiers
500 at unconditional_panic operation will cause a panic at runtime
501 at unconditional_recursion functions that cannot return without calling themselves
502 at unknown_crate_types unknown crate type found in `#[crate_type]` directive
503 at unknown_lints unrecognized lint attribute
504 at unnameable_test_items detects an item that cannot be named being marked as `#[test_case]`
505 at unreachable_code detects unreachable code paths
506 at unreachable_patterns detects unreachable patterns
507 at unreachable_pub `pub` items not reachable from crate root
508 at unsafe_code usage of `unsafe` code
509 at unsafe_op_in_unsafe_fn unsafe operations in unsafe functions without an explicit unsafe block are deprecated
510 at unstable_features enabling unstable features (deprecated. do not use)
511 at unstable_name_collisions detects name collision with an existing but unstable method
512 at unused_allocation detects unnecessary allocations that can be eliminated
513 at unused_assignments detect assignments that will never be read
514 at unused_attributes detects attributes that were not used by the compiler
515 at unused_braces unnecessary braces around an expression
516 at unused_comparisons comparisons made useless by limits of the types involved
517 at unused_crate_dependencies crate dependencies that are never used
518 at unused_doc_comments detects doc comments that aren't used by rustdoc
519 at unused_extern_crates extern crates that are never used
520 at unused_features unused features found in crate-level `#[feature]` directives
521 at unused_import_braces unnecessary braces around an imported item
522 at unused_imports imports that are never used
523 at unused_labels detects labels that are never used
524 at unused_lifetimes detects lifetime parameters that are never used
525 at unused_macros detects macros that were not used
526 at unused_must_use unused result of a type flagged as `#[must_use]`
527 at unused_mut detect mut variables which don't need to be mutable
528 at unused_parens `if`, `match`, `while` and `return` do not need parentheses
529 at unused_qualifications detects unnecessarily qualified names
530 at unused_results unused result of an expression in a statement
531 at unused_unsafe unnecessary use of an `unsafe` block
532 at unused_variables detect variables which are not used in any way
533 at variant_size_differences detects enums with widely varying variant sizes
534 at warnings mass-change the level for lints which produce warnings
535 at where_clauses_object_safety checks the object safety of where clauses
536 at while_true suggest using `loop { }` instead of `while true { }`
537 "#]],
538 )
539 }
540
541 #[test]
542 fn no_completion_for_incorrect_derive() {
543 check(
544 r#"
545#[derive{<|>)]
546struct Test {}
547"#,
548 expect![[r#""#]],
549 )
550 }
551
552 #[test]
553 fn derive_with_input_completion() {
554 check(
555 r#"
556#[derive(serde::Serialize, PartialEq, <|>)]
557struct Test {}
558"#,
559 expect![[r#"
560 at Clone
561 at Copy, Clone
562 at Debug
563 at Default
564 at Eq
565 at Hash
566 at Ord, PartialOrd, Eq
567 at PartialOrd
568 "#]],
569 )
570 }
571
572 #[test]
573 fn test_attribute_completion() {
574 check(
575 r#"#[<|>]"#,
576 expect![[r#"
577 at allow(…)
578 at cfg(…)
579 at cfg_attr(…)
580 at deny(…)
581 at deprecated = "…"
582 at derive(…)
583 at doc = "…"
584 at forbid(…)
585 at ignore = "…"
586 at inline(…)
587 at link
588 at link_name = "…"
589 at macro_export
590 at macro_use
591 at must_use = "…"
592 at no_mangle
593 at non_exhaustive
594 at path = "…"
595 at proc_macro
596 at proc_macro_attribute
597 at proc_macro_derive(…)
598 at repr(…)
599 at should_panic(…)
600 at target_feature = "…"
601 at test
602 at used
603 at warn(…)
604 "#]],
605 )
606 }
607
608 #[test]
609 fn test_attribute_completion_inside_nested_attr() {
610 check(r#"#[cfg(<|>)]"#, expect![[]])
611 }
612
613 #[test]
614 fn test_inner_attribute_completion() {
615 check(
616 r"#![<|>]",
617 expect![[r#"
618 at allow(…)
619 at cfg(…)
620 at cfg_attr(…)
621 at deny(…)
622 at deprecated = "…"
623 at derive(…)
624 at doc = "…"
625 at feature(…)
626 at forbid(…)
627 at global_allocator
628 at ignore = "…"
629 at inline(…)
630 at link
631 at link_name = "…"
632 at macro_export
633 at macro_use
634 at must_use = "…"
635 at no_mangle
636 at no_std
637 at non_exhaustive
638 at panic_handler
639 at path = "…"
640 at proc_macro
641 at proc_macro_attribute
642 at proc_macro_derive(…)
643 at recursion_limit = …
644 at repr(…)
645 at should_panic(…)
646 at target_feature = "…"
647 at test
648 at used
649 at warn(…)
650 at windows_subsystem = "…"
651 "#]],
652 );
653 }
654}