diff --git a/crates/ide_completion/src/completions/attribute/lint.rs b/crates/ide_completion/src/completions/attribute/lint.rs index dffb2d92d38..4f7930d0dd9 100644 --- a/crates/ide_completion/src/completions/attribute/lint.rs +++ b/crates/ide_completion/src/completions/attribute/lint.rs @@ -1,6 +1,6 @@ //! Completion for lints use ide_db::helpers::generated_lints::Lint; -use syntax::ast; +use syntax::{ast, T}; use crate::{ context::CompletionContext, @@ -16,7 +16,7 @@ pub(super) fn complete_lint( ) { if let Some(existing_lints) = super::parse_comma_sep_paths(derive_input) { for &Lint { label, description } in lints_completions { - let (ex_q, ex_name) = { + let (qual, name) = { // FIXME: change `Lint`'s label to not store a path in it but split the prefix off instead? let mut parts = label.split("::"); let ns_or_label = match parts.next() { @@ -29,7 +29,7 @@ pub(super) fn complete_lint( None => (None, ns_or_label), } }; - let repr_already_annotated = existing_lints + let lint_already_annotated = existing_lints .iter() .filter_map(|path| { let q = path.qualifier(); @@ -38,21 +38,26 @@ pub(super) fn complete_lint( } Some((q.and_then(|it| it.as_single_name_ref()), path.segment()?.name_ref()?)) }) - .any(|(q, name)| { - let qualifier_matches = match (q, ex_q) { + .any(|(q, name_ref)| { + let qualifier_matches = match (q, qual) { (None, None) => true, (None, Some(_)) => false, (Some(_), None) => false, (Some(q), Some(ns)) => q.text() == ns, }; - qualifier_matches && name.text() == ex_name + qualifier_matches && name_ref.text() == name }); - if repr_already_annotated { + if lint_already_annotated { continue; } + let insert = match qual { + Some(qual) if !ctx.previous_token_is(T![:]) => format!("{}::{}", qual, name), + _ => name.to_owned(), + }; let mut item = - CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), ex_name); + CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), label); item.kind(CompletionItemKind::Attribute) + .insert_text(insert) .documentation(hir::Documentation::new(description.to_owned())); item.add_to(acc) } diff --git a/crates/ide_completion/src/completions/attribute/repr.rs b/crates/ide_completion/src/completions/attribute/repr.rs index 95efe77c06d..9a12b8571c7 100644 --- a/crates/ide_completion/src/completions/attribute/repr.rs +++ b/crates/ide_completion/src/completions/attribute/repr.rs @@ -23,7 +23,7 @@ pub(super) fn complete_repr(acc: &mut Completions, ctx: &CompletionContext, inpu }) .any(|it| { let text = it.text(); - label == text || collides.contains(&text.as_str()) + lookup.unwrap_or(label) == text || collides.contains(&text.as_str()) }); if repr_already_annotated { continue; diff --git a/crates/ide_completion/src/tests/attribute.rs b/crates/ide_completion/src/tests/attribute.rs index 7d0bdc58210..9d22bb196bd 100644 --- a/crates/ide_completion/src/tests/attribute.rs +++ b/crates/ide_completion/src/tests/attribute.rs @@ -692,6 +692,24 @@ mod lint { r#"#[feature(box_syntax)] struct Test;"#, ) } + + #[test] + fn lint_clippy_unqualified() { + check_edit( + "clippy::as_conversions", + r#"#[allow($0)] struct Test;"#, + r#"#[allow(clippy::as_conversions)] struct Test;"#, + ); + } + + #[test] + fn lint_clippy_qualified() { + check_edit( + "clippy::as_conversions", + r#"#[allow(clippy::$0)] struct Test;"#, + r#"#[allow(clippy::as_conversions)] struct Test;"#, + ); + } } mod repr { @@ -742,7 +760,6 @@ mod repr { check_repr( r#"#[repr(align(1), $0)] struct Test;"#, expect![[r#" - at align($0) at transparent at C at u8 diff --git a/crates/rust-analyzer/tests/slow-tests/tidy.rs b/crates/rust-analyzer/tests/slow-tests/tidy.rs index bd34a5fda81..3866c178f8c 100644 --- a/crates/rust-analyzer/tests/slow-tests/tidy.rs +++ b/crates/rust-analyzer/tests/slow-tests/tidy.rs @@ -192,6 +192,8 @@ fn deny_clippy(path: &Path, text: &str) { "ide_db/src/helpers/generated_lints.rs", // The tests test clippy lint hovers "ide/src/hover/tests.rs", + // The tests test clippy lint completions + "ide_completion/src/tests/attribute.rs", ]; if ignore.iter().any(|p| path.ends_with(p)) { return;