mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
Merge #2160
2160: Set `deprecated` field on `CompletionItem`s r=matklad a=martskins This PR aims to address #2042 by setting the deprecated field for completion items. The setting the tags field for LSP 3.15 part still needs fixing, but that one is blocked due to lsp-types not being up to date with 3.15 yet. Co-authored-by: Martin Asquino <martin.asquino@gmail.com>
This commit is contained in:
commit
f9f1effd01
4 changed files with 113 additions and 1 deletions
|
@ -31,6 +31,34 @@ mod tests {
|
||||||
do_completion(code, CompletionKind::Reference)
|
do_completion(code, CompletionKind::Reference)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_record_literal_deprecated_field() {
|
||||||
|
let completions = complete(
|
||||||
|
r"
|
||||||
|
struct A {
|
||||||
|
#[deprecated]
|
||||||
|
the_field: u32,
|
||||||
|
}
|
||||||
|
fn foo() {
|
||||||
|
A { the<|> }
|
||||||
|
}
|
||||||
|
",
|
||||||
|
);
|
||||||
|
assert_debug_snapshot!(completions, @r###"
|
||||||
|
⋮[
|
||||||
|
⋮ CompletionItem {
|
||||||
|
⋮ label: "the_field",
|
||||||
|
⋮ source_range: [142; 145),
|
||||||
|
⋮ delete: [142; 145),
|
||||||
|
⋮ insert: "the_field",
|
||||||
|
⋮ kind: Field,
|
||||||
|
⋮ detail: "u32",
|
||||||
|
⋮ deprecated: true,
|
||||||
|
⋮ },
|
||||||
|
⋮]
|
||||||
|
"###);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_record_literal_field() {
|
fn test_record_literal_field() {
|
||||||
let completions = complete(
|
let completions = complete(
|
||||||
|
|
|
@ -44,6 +44,9 @@ pub struct CompletionItem {
|
||||||
/// Additional info to show in the UI pop up.
|
/// Additional info to show in the UI pop up.
|
||||||
detail: Option<String>,
|
detail: Option<String>,
|
||||||
documentation: Option<Documentation>,
|
documentation: Option<Documentation>,
|
||||||
|
|
||||||
|
/// Whether this item is marked as deprecated
|
||||||
|
deprecated: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// We use custom debug for CompletionItem to make `insta`'s diffs more readable.
|
// We use custom debug for CompletionItem to make `insta`'s diffs more readable.
|
||||||
|
@ -70,6 +73,9 @@ impl fmt::Debug for CompletionItem {
|
||||||
if let Some(documentation) = self.documentation() {
|
if let Some(documentation) = self.documentation() {
|
||||||
s.field("documentation", &documentation);
|
s.field("documentation", &documentation);
|
||||||
}
|
}
|
||||||
|
if self.deprecated {
|
||||||
|
s.field("deprecated", &true);
|
||||||
|
}
|
||||||
s.finish()
|
s.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,6 +138,7 @@ impl CompletionItem {
|
||||||
lookup: None,
|
lookup: None,
|
||||||
kind: None,
|
kind: None,
|
||||||
text_edit: None,
|
text_edit: None,
|
||||||
|
deprecated: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// What user sees in pop-up in the UI.
|
/// What user sees in pop-up in the UI.
|
||||||
|
@ -166,6 +173,10 @@ impl CompletionItem {
|
||||||
pub fn kind(&self) -> Option<CompletionItemKind> {
|
pub fn kind(&self) -> Option<CompletionItemKind> {
|
||||||
self.kind
|
self.kind
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn deprecated(&self) -> bool {
|
||||||
|
self.deprecated
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A helper to make `CompletionItem`s.
|
/// A helper to make `CompletionItem`s.
|
||||||
|
@ -181,6 +192,7 @@ pub(crate) struct Builder {
|
||||||
lookup: Option<String>,
|
lookup: Option<String>,
|
||||||
kind: Option<CompletionItemKind>,
|
kind: Option<CompletionItemKind>,
|
||||||
text_edit: Option<TextEdit>,
|
text_edit: Option<TextEdit>,
|
||||||
|
deprecated: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Builder {
|
impl Builder {
|
||||||
|
@ -208,6 +220,7 @@ impl Builder {
|
||||||
lookup: self.lookup,
|
lookup: self.lookup,
|
||||||
kind: self.kind,
|
kind: self.kind,
|
||||||
completion_kind: self.completion_kind,
|
completion_kind: self.completion_kind,
|
||||||
|
deprecated: self.deprecated.unwrap_or(false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub(crate) fn lookup_by(mut self, lookup: impl Into<String>) -> Builder {
|
pub(crate) fn lookup_by(mut self, lookup: impl Into<String>) -> Builder {
|
||||||
|
@ -254,6 +267,10 @@ impl Builder {
|
||||||
self.documentation = docs.map(Into::into);
|
self.documentation = docs.map(Into::into);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
pub(crate) fn set_deprecated(mut self, deprecated: bool) -> Builder {
|
||||||
|
self.deprecated = Some(deprecated);
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Into<CompletionItem> for Builder {
|
impl<'a> Into<CompletionItem> for Builder {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use hir::{db::HirDatabase, Docs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk};
|
use hir::{db::HirDatabase, Docs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk};
|
||||||
use join_to_string::join;
|
use join_to_string::join;
|
||||||
use ra_syntax::ast::NameOwner;
|
use ra_syntax::ast::{AttrsOwner, NameOwner};
|
||||||
use test_utils::tested_by;
|
use test_utils::tested_by;
|
||||||
|
|
||||||
use crate::completion::{
|
use crate::completion::{
|
||||||
|
@ -18,6 +18,11 @@ impl Completions {
|
||||||
field: hir::StructField,
|
field: hir::StructField,
|
||||||
substs: &hir::Substs,
|
substs: &hir::Substs,
|
||||||
) {
|
) {
|
||||||
|
let ast_node = field.source(ctx.db).ast;
|
||||||
|
let is_deprecated = match ast_node {
|
||||||
|
hir::FieldSource::Named(m) => is_deprecated(m),
|
||||||
|
hir::FieldSource::Pos(m) => is_deprecated(m),
|
||||||
|
};
|
||||||
CompletionItem::new(
|
CompletionItem::new(
|
||||||
CompletionKind::Reference,
|
CompletionKind::Reference,
|
||||||
ctx.source_range(),
|
ctx.source_range(),
|
||||||
|
@ -26,6 +31,7 @@ impl Completions {
|
||||||
.kind(CompletionItemKind::Field)
|
.kind(CompletionItemKind::Field)
|
||||||
.detail(field.ty(ctx.db).subst(substs).display(ctx.db).to_string())
|
.detail(field.ty(ctx.db).subst(substs).display(ctx.db).to_string())
|
||||||
.set_documentation(field.docs(ctx.db))
|
.set_documentation(field.docs(ctx.db))
|
||||||
|
.set_deprecated(is_deprecated)
|
||||||
.add_to(self);
|
.add_to(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,6 +185,7 @@ impl Completions {
|
||||||
CompletionItem::new(CompletionKind::Reference, ctx.source_range(), ¯o_declaration)
|
CompletionItem::new(CompletionKind::Reference, ctx.source_range(), ¯o_declaration)
|
||||||
.kind(CompletionItemKind::Macro)
|
.kind(CompletionItemKind::Macro)
|
||||||
.set_documentation(docs.clone())
|
.set_documentation(docs.clone())
|
||||||
|
.set_deprecated(is_deprecated(ast_node))
|
||||||
.detail(detail);
|
.detail(detail);
|
||||||
|
|
||||||
builder = if ctx.use_item_syntax.is_some() {
|
builder = if ctx.use_item_syntax.is_some() {
|
||||||
|
@ -211,6 +218,7 @@ impl Completions {
|
||||||
CompletionItemKind::Function
|
CompletionItemKind::Function
|
||||||
})
|
})
|
||||||
.set_documentation(func.docs(ctx.db))
|
.set_documentation(func.docs(ctx.db))
|
||||||
|
.set_deprecated(is_deprecated(ast_node))
|
||||||
.detail(detail);
|
.detail(detail);
|
||||||
|
|
||||||
// Add `<>` for generic types
|
// Add `<>` for generic types
|
||||||
|
@ -242,6 +250,7 @@ impl Completions {
|
||||||
CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.text().to_string())
|
CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.text().to_string())
|
||||||
.kind(CompletionItemKind::Const)
|
.kind(CompletionItemKind::Const)
|
||||||
.set_documentation(constant.docs(ctx.db))
|
.set_documentation(constant.docs(ctx.db))
|
||||||
|
.set_deprecated(is_deprecated(ast_node))
|
||||||
.detail(detail)
|
.detail(detail)
|
||||||
.add_to(self);
|
.add_to(self);
|
||||||
}
|
}
|
||||||
|
@ -257,11 +266,13 @@ impl Completions {
|
||||||
CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.text().to_string())
|
CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.text().to_string())
|
||||||
.kind(CompletionItemKind::TypeAlias)
|
.kind(CompletionItemKind::TypeAlias)
|
||||||
.set_documentation(type_alias.docs(ctx.db))
|
.set_documentation(type_alias.docs(ctx.db))
|
||||||
|
.set_deprecated(is_deprecated(type_def))
|
||||||
.detail(detail)
|
.detail(detail)
|
||||||
.add_to(self);
|
.add_to(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir::EnumVariant) {
|
pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir::EnumVariant) {
|
||||||
|
let is_deprecated = is_deprecated(variant.source(ctx.db).ast);
|
||||||
let name = match variant.name(ctx.db) {
|
let name = match variant.name(ctx.db) {
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
None => return,
|
None => return,
|
||||||
|
@ -274,11 +285,16 @@ impl Completions {
|
||||||
CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string())
|
CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string())
|
||||||
.kind(CompletionItemKind::EnumVariant)
|
.kind(CompletionItemKind::EnumVariant)
|
||||||
.set_documentation(variant.docs(ctx.db))
|
.set_documentation(variant.docs(ctx.db))
|
||||||
|
.set_deprecated(is_deprecated)
|
||||||
.detail(detail)
|
.detail(detail)
|
||||||
.add_to(self);
|
.add_to(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_deprecated(node: impl AttrsOwner) -> bool {
|
||||||
|
node.attrs().filter_map(|x| x.simple_name()).any(|x| x == "deprecated")
|
||||||
|
}
|
||||||
|
|
||||||
fn has_non_default_type_params(def: hir::GenericDef, db: &db::RootDatabase) -> bool {
|
fn has_non_default_type_params(def: hir::GenericDef, db: &db::RootDatabase) -> bool {
|
||||||
let subst = db.generic_defaults(def);
|
let subst = db.generic_defaults(def);
|
||||||
subst.iter().any(|ty| ty == &Ty::Unknown)
|
subst.iter().any(|ty| ty == &Ty::Unknown)
|
||||||
|
@ -295,6 +311,56 @@ mod tests {
|
||||||
do_completion(code, CompletionKind::Reference)
|
do_completion(code, CompletionKind::Reference)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sets_deprecated_flag_in_completion_items() {
|
||||||
|
assert_debug_snapshot!(
|
||||||
|
do_reference_completion(
|
||||||
|
r#"
|
||||||
|
#[deprecated]
|
||||||
|
fn something_deprecated() {}
|
||||||
|
|
||||||
|
#[deprecated(since = "1.0.0")]
|
||||||
|
fn something_else_deprecated() {}
|
||||||
|
|
||||||
|
fn main() { som<|> }
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
@r###"
|
||||||
|
[
|
||||||
|
CompletionItem {
|
||||||
|
label: "main()",
|
||||||
|
source_range: [203; 206),
|
||||||
|
delete: [203; 206),
|
||||||
|
insert: "main()$0",
|
||||||
|
kind: Function,
|
||||||
|
lookup: "main",
|
||||||
|
detail: "fn main()",
|
||||||
|
},
|
||||||
|
CompletionItem {
|
||||||
|
label: "something_deprecated()",
|
||||||
|
source_range: [203; 206),
|
||||||
|
delete: [203; 206),
|
||||||
|
insert: "something_deprecated()$0",
|
||||||
|
kind: Function,
|
||||||
|
lookup: "something_deprecated",
|
||||||
|
detail: "fn something_deprecated()",
|
||||||
|
deprecated: true,
|
||||||
|
},
|
||||||
|
CompletionItem {
|
||||||
|
label: "something_else_deprecated()",
|
||||||
|
source_range: [203; 206),
|
||||||
|
delete: [203; 206),
|
||||||
|
insert: "something_else_deprecated()$0",
|
||||||
|
kind: Function,
|
||||||
|
lookup: "something_else_deprecated",
|
||||||
|
detail: "fn something_else_deprecated()",
|
||||||
|
deprecated: true,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn inserts_parens_for_function_calls() {
|
fn inserts_parens_for_function_calls() {
|
||||||
covers!(inserts_parens_for_function_calls);
|
covers!(inserts_parens_for_function_calls);
|
||||||
|
|
|
@ -127,6 +127,7 @@ impl ConvWith<(&LineIndex, LineEndings)> for CompletionItem {
|
||||||
text_edit: Some(text_edit),
|
text_edit: Some(text_edit),
|
||||||
additional_text_edits: Some(additional_text_edits),
|
additional_text_edits: Some(additional_text_edits),
|
||||||
documentation: self.documentation().map(|it| it.conv()),
|
documentation: self.documentation().map(|it| it.conv()),
|
||||||
|
deprecated: Some(self.deprecated()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
res.insert_text_format = Some(match self.insert_text_format() {
|
res.insert_text_format = Some(match self.insert_text_format() {
|
||||||
|
|
Loading…
Reference in a new issue