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:
bors[bot]
2019-11-03 14:41:30 +00:00
committed by GitHub
4 changed files with 113 additions and 1 deletions
@@ -31,6 +31,34 @@ fn complete(code: &str) -> Vec<CompletionItem> {
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]
fn test_record_literal_field() {
let completions = complete(
@@ -44,6 +44,9 @@ pub struct CompletionItem {
/// Additional info to show in the UI pop up.
detail: Option<String>,
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.
@@ -70,6 +73,9 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(documentation) = self.documentation() {
s.field("documentation", &documentation);
}
if self.deprecated {
s.field("deprecated", &true);
}
s.finish()
}
}
@@ -132,6 +138,7 @@ pub(crate) fn new(
lookup: None,
kind: None,
text_edit: None,
deprecated: None,
}
}
/// What user sees in pop-up in the UI.
@@ -166,6 +173,10 @@ pub fn lookup(&self) -> &str {
pub fn kind(&self) -> Option<CompletionItemKind> {
self.kind
}
pub fn deprecated(&self) -> bool {
self.deprecated
}
}
/// A helper to make `CompletionItem`s.
@@ -181,6 +192,7 @@ pub(crate) struct Builder {
lookup: Option<String>,
kind: Option<CompletionItemKind>,
text_edit: Option<TextEdit>,
deprecated: Option<bool>,
}
impl Builder {
@@ -208,6 +220,7 @@ pub(crate) fn build(self) -> CompletionItem {
lookup: self.lookup,
kind: self.kind,
completion_kind: self.completion_kind,
deprecated: self.deprecated.unwrap_or(false),
}
}
pub(crate) fn lookup_by(mut self, lookup: impl Into<String>) -> Builder {
@@ -254,6 +267,10 @@ pub(crate) fn set_documentation(mut self, docs: Option<Documentation>) -> Builde
self.documentation = docs.map(Into::into);
self
}
pub(crate) fn set_deprecated(mut self, deprecated: bool) -> Builder {
self.deprecated = Some(deprecated);
self
}
}
impl<'a> Into<CompletionItem> for Builder {
@@ -2,7 +2,7 @@
use hir::{db::HirDatabase, Docs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk};
use join_to_string::join;
use ra_syntax::ast::NameOwner;
use ra_syntax::ast::{AttrsOwner, NameOwner};
use test_utils::tested_by;
use crate::completion::{
@@ -18,6 +18,11 @@ pub(crate) fn add_field(
field: hir::StructField,
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(
CompletionKind::Reference,
ctx.source_range(),
@@ -26,6 +31,7 @@ pub(crate) fn add_field(
.kind(CompletionItemKind::Field)
.detail(field.ty(ctx.db).subst(substs).display(ctx.db).to_string())
.set_documentation(field.docs(ctx.db))
.set_deprecated(is_deprecated)
.add_to(self);
}
@@ -179,6 +185,7 @@ pub(crate) fn add_macro(
CompletionItem::new(CompletionKind::Reference, ctx.source_range(), &macro_declaration)
.kind(CompletionItemKind::Macro)
.set_documentation(docs.clone())
.set_deprecated(is_deprecated(ast_node))
.detail(detail);
builder = if ctx.use_item_syntax.is_some() {
@@ -211,6 +218,7 @@ fn add_function_with_name(
CompletionItemKind::Function
})
.set_documentation(func.docs(ctx.db))
.set_deprecated(is_deprecated(ast_node))
.detail(detail);
// Add `<>` for generic types
@@ -242,6 +250,7 @@ pub(crate) fn add_const(&mut self, ctx: &CompletionContext, constant: hir::Const
CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.text().to_string())
.kind(CompletionItemKind::Const)
.set_documentation(constant.docs(ctx.db))
.set_deprecated(is_deprecated(ast_node))
.detail(detail)
.add_to(self);
}
@@ -257,11 +266,13 @@ pub(crate) fn add_type_alias(&mut self, ctx: &CompletionContext, type_alias: hir
CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.text().to_string())
.kind(CompletionItemKind::TypeAlias)
.set_documentation(type_alias.docs(ctx.db))
.set_deprecated(is_deprecated(type_def))
.detail(detail)
.add_to(self);
}
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) {
Some(it) => it,
None => return,
@@ -274,11 +285,16 @@ pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir:
CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string())
.kind(CompletionItemKind::EnumVariant)
.set_documentation(variant.docs(ctx.db))
.set_deprecated(is_deprecated)
.detail(detail)
.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 {
let subst = db.generic_defaults(def);
subst.iter().any(|ty| ty == &Ty::Unknown)
@@ -295,6 +311,56 @@ fn do_reference_completion(code: &str) -> Vec<CompletionItem> {
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]
fn inserts_parens_for_function_calls() {
covers!(inserts_parens_for_function_calls);
+1
View File
@@ -127,6 +127,7 @@ fn conv_with(self, ctx: (&LineIndex, LineEndings)) -> ::lsp_types::CompletionIte
text_edit: Some(text_edit),
additional_text_edits: Some(additional_text_edits),
documentation: self.documentation().map(|it| it.conv()),
deprecated: Some(self.deprecated()),
..Default::default()
};
res.insert_text_format = Some(match self.insert_text_format() {