Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22085 from ada4a/18554-float-consts
feat(completion): reduce relevance for deprecated items
Chayim Refael Friedman 4 weeks ago
parent 4429a9c · parent 24dca9f · commit 4c21cec
-rw-r--r--crates/ide-completion/src/context/analysis.rs10
-rw-r--r--crates/ide-completion/src/item.rs46
-rw-r--r--crates/ide-completion/src/render.rs206
-rw-r--r--crates/ide-db/src/imports/import_assets.rs2
-rw-r--r--crates/test-utils/src/minicore.rs27
5 files changed, 266 insertions, 25 deletions
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index 58c0f683a3..c8068d6fc4 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -2094,12 +2094,12 @@ fn next_non_trivia_token(e: impl Into<SyntaxElement>) -> Option<SyntaxToken> {
}
fn next_non_trivia_sibling(ele: SyntaxElement) -> Option<SyntaxElement> {
- let mut e = ele.next_sibling_or_token();
- while let Some(inner) = e {
- if !inner.kind().is_trivia() {
- return Some(inner);
+ let mut e = ele;
+ while let Some(next) = e.next_sibling_or_token() {
+ if !next.kind().is_trivia() {
+ return Some(next);
} else {
- e = inner.next_sibling_or_token();
+ e = next;
}
}
None
diff --git a/crates/ide-completion/src/item.rs b/crates/ide-completion/src/item.rs
index 6abf4f632a..6b34bf07bb 100644
--- a/crates/ide-completion/src/item.rs
+++ b/crates/ide-completion/src/item.rs
@@ -61,6 +61,9 @@ pub struct CompletionItem {
pub documentation: Option<Documentation<'static>>,
/// Whether this item is marked as deprecated
+ ///
+ /// NOTE: this field is used in the LSP protocol. For the use of this information in completion
+ /// scoring, see [`CompletionRelevance::is_deprecated`].
pub deprecated: bool,
/// If completing a function call, ask the editor to show parameter popup
@@ -194,6 +197,11 @@ pub struct CompletionRelevance {
pub is_skipping_completion: bool,
/// if inherent impl already exists in current module, user may not want to implement it again.
pub has_local_inherent_impl: bool,
+ /// Set when the completion item is deprecated.
+ ///
+ /// NOTE: This is duplicated from [`CompletionItem::deprecated`] in order to allow using this
+ /// information in the calculation of the relevance score.
+ pub is_deprecated: bool,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct CompletionRelevanceTraitInfo {
@@ -286,6 +294,7 @@ impl CompletionRelevance {
function,
is_skipping_completion,
has_local_inherent_impl,
+ is_deprecated,
} = self;
// only applicable for completions within use items
@@ -362,6 +371,11 @@ impl CompletionRelevance {
score -= 5;
}
+ // lower rank for deprecated items
+ if is_deprecated {
+ score -= 5;
+ }
+
score
}
@@ -590,6 +604,9 @@ impl Builder {
None => TextEdit::replace(self.source_range, insert_text),
};
+ // Copy `deprecated` to `self.relevance.is_deprecated`
+ let relevance = CompletionRelevance { is_deprecated: self.deprecated, ..self.relevance };
+
let import_to_add = self
.imports_to_add
.into_iter()
@@ -622,7 +639,7 @@ impl Builder {
kind: self.kind,
deprecated: self.deprecated,
trigger_call_info: self.trigger_call_info,
- relevance: self.relevance,
+ relevance,
ref_match: self.ref_match,
import_to_add,
}
@@ -693,6 +710,15 @@ impl Builder {
self
}
pub(crate) fn set_relevance(&mut self, relevance: CompletionRelevance) -> &mut Builder {
+ // The default value of `CompletionRelevance.is_deprecated` is `false`, so it being `true`
+ // would mean it was set manually. Advise using the other function instead.
+ //
+ // This is technically not necessary, because `deprecated` will get reconciled in
+ // `Builder::build` anyway -- it just helps keep the callers consistent.
+ assert!(
+ !relevance.is_deprecated,
+ "`deprecated` should be set using `Builder::set_deprecated` instead"
+ );
self.relevance = relevance;
self
}
@@ -727,9 +753,25 @@ mod tests {
use test_utils::assert_eq_text;
use super::{
- CompletionRelevance, CompletionRelevancePostfixMatch, CompletionRelevanceTypeMatch,
+ CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevancePostfixMatch,
+ CompletionRelevanceTypeMatch,
};
+ #[test]
+ fn builder_deprecated_from_set_deprecated() {
+ // setting just `item.deprecated` also sets `item.relevance.is_deprecated`
+ let mut builder = CompletionItem::new(
+ CompletionItemKind::Expression,
+ Default::default(),
+ "",
+ syntax::Edition::DEFAULT,
+ );
+ builder.set_deprecated(true);
+ let item = builder.build(&Default::default());
+ assert!(item.deprecated);
+ assert!(item.relevance.is_deprecated);
+ }
+
/// Check that these are CompletionRelevance are sorted in ascending order
/// by their relevance score.
///
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs
index a636c0603b..608dec1285 100644
--- a/crates/ide-completion/src/render.rs
+++ b/crates/ide-completion/src/render.rs
@@ -828,7 +828,7 @@ mod tests {
items.push(format!(
"{tag} {} {} {relevance}\n",
it.label.primary,
- it.label.detail_right.clone().unwrap_or_default(),
+ it.label.detail_right.as_deref().unwrap_or_default(),
));
if let Some((label, _indel, relevance)) = it.ref_match() {
@@ -844,24 +844,33 @@ mod tests {
expect.assert_eq(&actual);
fn display_relevance(relevance: CompletionRelevance) -> String {
- let relevance_factors = vec![
- (relevance.type_match == Some(CompletionRelevanceTypeMatch::Exact), "type"),
- (
- relevance.type_match == Some(CompletionRelevanceTypeMatch::CouldUnify),
- "type_could_unify",
- ),
- (relevance.exact_name_match, "name"),
- (relevance.is_local, "local"),
- (
- relevance.postfix_match == Some(CompletionRelevancePostfixMatch::Exact),
- "snippet",
- ),
- (relevance.trait_.is_some_and(|it| it.is_op_method), "op_method"),
- (relevance.requires_import, "requires_import"),
- (relevance.has_local_inherent_impl, "has_local_inherent_impl"),
+ let CompletionRelevance {
+ exact_name_match,
+ type_match,
+ is_local,
+ trait_,
+ is_name_already_imported: _,
+ requires_import,
+ is_private_editable: _,
+ postfix_match,
+ function: _,
+ is_skipping_completion: _,
+ has_local_inherent_impl,
+ is_deprecated,
+ } = relevance;
+ let relevance_factors = [
+ (type_match == Some(CompletionRelevanceTypeMatch::Exact), "type"),
+ (type_match == Some(CompletionRelevanceTypeMatch::CouldUnify), "type_could_unify"),
+ (exact_name_match, "name"),
+ (is_local, "local"),
+ (postfix_match == Some(CompletionRelevancePostfixMatch::Exact), "snippet"),
+ (trait_.is_some_and(|it| it.is_op_method), "op_method"),
+ (requires_import, "requires_import"),
+ (has_local_inherent_impl, "has_local_inherent_impl"),
+ (is_deprecated, "deprecated"),
]
.into_iter()
- .filter_map(|(cond, desc)| if cond { Some(desc) } else { None })
+ .filter_map(|(cond, desc)| cond.then_some(desc))
.join("+");
format!("[{relevance_factors}]")
@@ -1242,6 +1251,7 @@ fn main() { Foo::Fo$0 }
),
is_skipping_completion: false,
has_local_inherent_impl: false,
+ is_deprecated: false,
},
trigger_call_info: true,
},
@@ -1293,6 +1303,7 @@ fn main() { Foo::Fo$0 }
),
is_skipping_completion: false,
has_local_inherent_impl: false,
+ is_deprecated: false,
},
trigger_call_info: true,
},
@@ -1437,6 +1448,7 @@ fn main() { Foo::Fo$0 }
),
is_skipping_completion: false,
has_local_inherent_impl: false,
+ is_deprecated: false,
},
trigger_call_info: true,
},
@@ -1521,6 +1533,7 @@ fn main() { let _: m::Spam = S$0 }
),
is_skipping_completion: false,
has_local_inherent_impl: false,
+ is_deprecated: false,
},
trigger_call_info: true,
},
@@ -1558,6 +1571,7 @@ fn main() { let _: m::Spam = S$0 }
),
is_skipping_completion: false,
has_local_inherent_impl: false,
+ is_deprecated: false,
},
trigger_call_info: true,
},
@@ -1589,6 +1603,20 @@ fn main() { som$0 }
Module,
),
deprecated: true,
+ relevance: CompletionRelevance {
+ exact_name_match: false,
+ type_match: None,
+ is_local: false,
+ trait_: None,
+ is_name_already_imported: false,
+ requires_import: false,
+ is_private_editable: false,
+ postfix_match: None,
+ function: None,
+ is_skipping_completion: false,
+ has_local_inherent_impl: false,
+ is_deprecated: true,
+ },
},
]
"#]],
@@ -1634,6 +1662,20 @@ fn main() { som$0 }
lookup: "something_deprecated",
detail: "fn()",
deprecated: true,
+ relevance: CompletionRelevance {
+ exact_name_match: false,
+ type_match: None,
+ is_local: false,
+ trait_: None,
+ is_name_already_imported: false,
+ requires_import: false,
+ is_private_editable: false,
+ postfix_match: None,
+ function: None,
+ is_skipping_completion: false,
+ has_local_inherent_impl: false,
+ is_deprecated: true,
+ },
},
]
"#]],
@@ -1663,6 +1705,20 @@ fn main() { A$0 }
),
detail: "A",
deprecated: true,
+ relevance: CompletionRelevance {
+ exact_name_match: false,
+ type_match: None,
+ is_local: false,
+ trait_: None,
+ is_name_already_imported: false,
+ requires_import: false,
+ is_private_editable: false,
+ postfix_match: None,
+ function: None,
+ is_skipping_completion: false,
+ has_local_inherent_impl: false,
+ is_deprecated: true,
+ },
},
]
"#]],
@@ -1692,6 +1748,20 @@ fn main() { A$0 }
),
detail: "A",
deprecated: true,
+ relevance: CompletionRelevance {
+ exact_name_match: false,
+ type_match: None,
+ is_local: false,
+ trait_: None,
+ is_name_already_imported: false,
+ requires_import: false,
+ is_private_editable: false,
+ postfix_match: None,
+ function: None,
+ is_skipping_completion: false,
+ has_local_inherent_impl: false,
+ is_deprecated: true,
+ },
},
]
"#]],
@@ -1741,6 +1811,7 @@ fn main() { A::$0 }
),
is_skipping_completion: false,
has_local_inherent_impl: false,
+ is_deprecated: false,
},
trigger_call_info: true,
},
@@ -1776,6 +1847,7 @@ fn main() { A::$0 }
),
is_skipping_completion: false,
has_local_inherent_impl: false,
+ is_deprecated: true,
},
trigger_call_info: true,
},
@@ -1807,6 +1879,20 @@ fn main() { A$0 }
),
detail: "i32",
deprecated: true,
+ relevance: CompletionRelevance {
+ exact_name_match: false,
+ type_match: None,
+ is_local: false,
+ trait_: None,
+ is_name_already_imported: false,
+ requires_import: false,
+ is_private_editable: false,
+ postfix_match: None,
+ function: None,
+ is_skipping_completion: false,
+ has_local_inherent_impl: false,
+ is_deprecated: true,
+ },
},
]
"#]],
@@ -1836,6 +1922,20 @@ fn main() { A$0 }
),
detail: "i32",
deprecated: true,
+ relevance: CompletionRelevance {
+ exact_name_match: false,
+ type_match: None,
+ is_local: false,
+ trait_: None,
+ is_name_already_imported: false,
+ requires_import: false,
+ is_private_editable: false,
+ postfix_match: None,
+ function: None,
+ is_skipping_completion: false,
+ has_local_inherent_impl: false,
+ is_deprecated: true,
+ },
},
]
"#]],
@@ -1862,6 +1962,20 @@ impl A$0
Trait,
),
deprecated: true,
+ relevance: CompletionRelevance {
+ exact_name_match: false,
+ type_match: None,
+ is_local: false,
+ trait_: None,
+ is_name_already_imported: false,
+ requires_import: false,
+ is_private_editable: false,
+ postfix_match: None,
+ function: None,
+ is_skipping_completion: false,
+ has_local_inherent_impl: false,
+ is_deprecated: true,
+ },
},
]
"#]],
@@ -1888,6 +2002,20 @@ fn main() { A$0 }
TypeAlias,
),
deprecated: true,
+ relevance: CompletionRelevance {
+ exact_name_match: false,
+ type_match: None,
+ is_local: false,
+ trait_: None,
+ is_name_already_imported: false,
+ requires_import: false,
+ is_private_editable: false,
+ postfix_match: None,
+ function: None,
+ is_skipping_completion: false,
+ has_local_inherent_impl: false,
+ is_deprecated: true,
+ },
},
]
"#]],
@@ -1918,6 +2046,20 @@ fn main() { a$0 }
lookup: "a!",
detail: "macro_rules! a",
deprecated: true,
+ relevance: CompletionRelevance {
+ exact_name_match: false,
+ type_match: None,
+ is_local: false,
+ trait_: None,
+ is_name_already_imported: false,
+ requires_import: false,
+ is_private_editable: false,
+ postfix_match: None,
+ function: None,
+ is_skipping_completion: false,
+ has_local_inherent_impl: false,
+ is_deprecated: true,
+ },
},
]
"#]],
@@ -1960,6 +2102,7 @@ fn main() { A { the$0 } }
function: None,
is_skipping_completion: false,
has_local_inherent_impl: false,
+ is_deprecated: true,
},
},
]
@@ -2020,6 +2163,7 @@ impl S {
),
is_skipping_completion: false,
has_local_inherent_impl: false,
+ is_deprecated: false,
},
},
CompletionItem {
@@ -2112,6 +2256,7 @@ use self::E::*;
),
is_skipping_completion: false,
has_local_inherent_impl: false,
+ is_deprecated: false,
},
trigger_call_info: true,
},
@@ -2183,6 +2328,7 @@ fn foo(s: S) { s.$0 }
),
is_skipping_completion: false,
has_local_inherent_impl: false,
+ is_deprecated: false,
},
},
]
@@ -2396,6 +2542,7 @@ fn f() -> i32 {
function: None,
is_skipping_completion: false,
has_local_inherent_impl: false,
+ is_deprecated: false,
},
},
]
@@ -2502,6 +2649,7 @@ fn main() {
function: None,
is_skipping_completion: false,
has_local_inherent_impl: false,
+ is_deprecated: false,
},
ref_match: "&@65",
},
@@ -3299,6 +3447,7 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 }
),
is_skipping_completion: false,
has_local_inherent_impl: false,
+ is_deprecated: false,
},
ref_match: "&@107",
},
@@ -3387,6 +3536,7 @@ fn foo() {
function: None,
is_skipping_completion: false,
has_local_inherent_impl: false,
+ is_deprecated: false,
},
},
]
@@ -3446,6 +3596,7 @@ fn main() {
),
is_skipping_completion: false,
has_local_inherent_impl: false,
+ is_deprecated: false,
},
ref_match: "&@92",
},
@@ -3641,6 +3792,25 @@ fn f() {
}
#[test]
+ /// Issue: https://github.com/rust-lang/rust-analyzer/issues/18554
+ fn float_consts_relevance() {
+ check_relevance(
+ r#"
+//- minicore: float_consts
+fn main() {
+ let x = f32::INF$0
+}
+"#,
+ expect![[r#"
+ ct INFINITY pub const INFINITY: f32 []
+ ct NEG_INFINITY pub const NEG_INFINITY: f32 []
+ ct INFINITY f32 [type_could_unify+requires_import+deprecated]
+ ct NEG_INFINITY f32 [type_could_unify+requires_import+deprecated]
+ "#]],
+ );
+ }
+
+ #[test]
fn completes_struct_with_raw_identifier() {
check_edit(
"type",
@@ -3917,6 +4087,7 @@ fn main() {
function: None,
is_skipping_completion: false,
has_local_inherent_impl: false,
+ is_deprecated: false,
},
},
CompletionItem {
@@ -3952,6 +4123,7 @@ fn main() {
function: None,
is_skipping_completion: false,
has_local_inherent_impl: false,
+ is_deprecated: false,
},
},
]
diff --git a/crates/ide-db/src/imports/import_assets.rs b/crates/ide-db/src/imports/import_assets.rs
index 9018552afb..4f05714a55 100644
--- a/crates/ide-db/src/imports/import_assets.rs
+++ b/crates/ide-db/src/imports/import_assets.rs
@@ -314,7 +314,7 @@ pub struct LocatedImport {
pub item_to_import: ItemInNs,
/// The path import candidate, resolved.
///
- /// Not necessary matches the import:
+ /// Not necessarily matches the import:
/// For any associated constant from the trait, we try to access as `some::path::SomeStruct::ASSOC_`
/// the original item is the associated constant, but the import has to be a trait that
/// defines this constant.
diff --git a/crates/test-utils/src/minicore.rs b/crates/test-utils/src/minicore.rs
index a51698aca8..c447870e96 100644
--- a/crates/test-utils/src/minicore.rs
+++ b/crates/test-utils/src/minicore.rs
@@ -33,6 +33,7 @@
//! env: option
//! eq: sized
//! error: fmt
+//! float_consts:
//! fmt: option, result, transmute, coerce_unsized, copy, clone, derive
//! fmt_before_1_93_0: fmt
//! fmt_before_1_89_0: fmt_before_1_93_0
@@ -2181,6 +2182,32 @@ pub mod error {
}
// endregion:error
+// region:float_consts
+impl f32 {
+ pub const INFINITY: f32 = 0.0;
+ pub const NEG_INFINITY: f32 = -0.0;
+}
+
+impl f64 {
+ pub const INFINITY: f64 = 0.0;
+ pub const NEG_INFINITY: f64 = -0.0;
+}
+
+pub mod f32 {
+ #[deprecated]
+ pub const INFINITY: f32 = 0.0;
+ #[deprecated]
+ pub const NEG_INFINITY: f32 = -0.0;
+}
+
+pub mod f64 {
+ #[deprecated]
+ pub const INFINITY: f64 = 0.0;
+ #[deprecated]
+ pub const NEG_INFINITY: f64 = -0.0;
+}
+// endregion:float_consts
+
// region:column
#[rustc_builtin_macro]
#[macro_export]