summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/rust-analyzer/crates/ide-completion/src/context.rs')
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context.rs45
1 files changed, 38 insertions, 7 deletions
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
index 8cbf89e9c..7b145f3c1 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
@@ -17,7 +17,7 @@ use ide_db::{
};
use syntax::{
ast::{self, AttrKind, NameOrNameRef},
- AstNode,
+ AstNode, SmolStr,
SyntaxKind::{self, *},
SyntaxToken, TextRange, TextSize, T,
};
@@ -367,6 +367,8 @@ pub(crate) struct CompletionContext<'a> {
pub(super) krate: hir::Crate,
/// The module of the `scope`.
pub(super) module: hir::Module,
+ /// Whether nightly toolchain is used. Cached since this is looked up a lot.
+ is_nightly: bool,
/// The expected name of what we are completing.
/// This is usually the parameter name of the function argument we are completing.
@@ -386,7 +388,7 @@ pub(crate) struct CompletionContext<'a> {
pub(super) depth_from_crate_root: usize,
}
-impl<'a> CompletionContext<'a> {
+impl CompletionContext<'_> {
/// The range of the identifier that is being completed.
pub(crate) fn source_range(&self) -> TextRange {
let kind = self.original_token.kind();
@@ -441,6 +443,14 @@ impl<'a> CompletionContext<'a> {
self.is_visible_impl(&vis, &attrs, item.krate(self.db))
}
+ pub(crate) fn doc_aliases<I>(&self, item: &I) -> Vec<SmolStr>
+ where
+ I: hir::HasAttrs + Copy,
+ {
+ let attrs = item.attrs(self.db);
+ attrs.doc_aliases().collect()
+ }
+
/// Check if an item is `#[doc(hidden)]`.
pub(crate) fn is_item_hidden(&self, item: &hir::ItemInNs) -> bool {
let attrs = item.attrs(self.db);
@@ -451,6 +461,12 @@ impl<'a> CompletionContext<'a> {
}
}
+ /// Checks whether this item should be listed in regards to stability. Returns `true` if we should.
+ pub(crate) fn check_stability(&self, attrs: Option<&hir::Attrs>) -> bool {
+ let Some(attrs) = attrs else { return true; };
+ !attrs.is_unstable() || self.is_nightly
+ }
+
/// Whether the given trait is an operator trait or not.
pub(crate) fn is_ops_trait(&self, trait_: hir::Trait) -> bool {
match trait_.attrs(self.db).lang() {
@@ -491,21 +507,22 @@ impl<'a> CompletionContext<'a> {
);
}
- /// A version of [`SemanticsScope::process_all_names`] that filters out `#[doc(hidden)]` items.
- pub(crate) fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef)) {
+ /// A version of [`SemanticsScope::process_all_names`] that filters out `#[doc(hidden)]` items and
+ /// passes all doc-aliases along, to funnel it into [`Completions::add_path_resolution`].
+ pub(crate) fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef, Vec<SmolStr>)) {
let _p = profile::span("CompletionContext::process_all_names");
self.scope.process_all_names(&mut |name, def| {
if self.is_scope_def_hidden(def) {
return;
}
-
- f(name, def);
+ let doc_aliases = self.doc_aliases_in_scope(def);
+ f(name, def, doc_aliases);
});
}
pub(crate) fn process_all_names_raw(&self, f: &mut dyn FnMut(Name, ScopeDef)) {
let _p = profile::span("CompletionContext::process_all_names_raw");
- self.scope.process_all_names(&mut |name, def| f(name, def));
+ self.scope.process_all_names(f);
}
fn is_scope_def_hidden(&self, scope_def: ScopeDef) -> bool {
@@ -545,6 +562,14 @@ impl<'a> CompletionContext<'a> {
// `doc(hidden)` items are only completed within the defining crate.
self.krate != defining_crate && attrs.has_doc_hidden()
}
+
+ pub(crate) fn doc_aliases_in_scope(&self, scope_def: ScopeDef) -> Vec<SmolStr> {
+ if let Some(attrs) = scope_def.attrs(self.db) {
+ attrs.doc_aliases().collect()
+ } else {
+ vec![]
+ }
+ }
}
// CompletionContext construction
@@ -615,6 +640,11 @@ impl<'a> CompletionContext<'a> {
let krate = scope.krate();
let module = scope.module();
+ let toolchain = db.crate_graph()[krate.into()].channel;
+ // `toolchain == None` means we're in some detached files. Since we have no information on
+ // the toolchain being used, let's just allow unstable items to be listed.
+ let is_nightly = matches!(toolchain, Some(base_db::ReleaseChannel::Nightly) | None);
+
let mut locals = FxHashMap::default();
scope.process_all_names(&mut |name, scope| {
if let ScopeDef::Local(local) = scope {
@@ -634,6 +664,7 @@ impl<'a> CompletionContext<'a> {
token,
krate,
module,
+ is_nightly,
expected_name,
expected_type,
qualifier_ctx,