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