This commit is contained in:
Lukas Wirth 2022-03-14 20:36:35 +01:00
parent 301711ee71
commit fbc1d2a514
4 changed files with 38 additions and 35 deletions

View File

@ -1327,14 +1327,14 @@ impl<'a> SemanticsScope<'a> {
resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()), resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()),
resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()), resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()),
resolver::ScopeDef::GenericParam(id) => ScopeDef::GenericParam(id.into()), resolver::ScopeDef::GenericParam(id) => ScopeDef::GenericParam(id.into()),
resolver::ScopeDef::Local(pat_id) => { resolver::ScopeDef::Local(pat_id) => match self.resolver.body_owner() {
let parent = self.resolver.body_owner().unwrap(); Some(parent) => ScopeDef::Local(Local { parent, pat_id }),
ScopeDef::Local(Local { parent, pat_id }) None => continue,
} },
resolver::ScopeDef::Label(label_id) => { resolver::ScopeDef::Label(label_id) => match self.resolver.body_owner() {
let parent = self.resolver.body_owner().unwrap(); Some(parent) => ScopeDef::Label(Label { parent, label_id }),
ScopeDef::Label(Label { parent, label_id }) None => continue,
} },
}; };
f(name.clone(), def) f(name.clone(), def)
} }

View File

@ -1,5 +1,5 @@
//! Name resolution façade. //! Name resolution façade.
use std::sync::Arc; use std::{hash::BuildHasherDefault, sync::Arc};
use base_db::CrateId; use base_db::CrateId;
use hir_expand::name::{name, Name}; use hir_expand::name::{name, Name};
@ -352,7 +352,7 @@ impl Resolver {
/// Returns a set of names available in the current scope. /// Returns a set of names available in the current scope.
/// ///
/// Note that this is a somewhat fuzzy concept -- internally, the compiler /// Note that this is a somewhat fuzzy concept -- internally, the compiler
/// doesn't necessary follow a strict scoping discipline. Rathe, it just /// doesn't necessary follow a strict scoping discipline. Rather, it just
/// tells for each ident what it resolves to. /// tells for each ident what it resolves to.
/// ///
/// A good example is something like `str::from_utf8`. From scopes point of /// A good example is something like `str::from_utf8`. From scopes point of
@ -387,10 +387,13 @@ impl Resolver {
/// The result is ordered *roughly* from the innermost scope to the /// The result is ordered *roughly* from the innermost scope to the
/// outermost: when the name is introduced in two namespaces in two scopes, /// outermost: when the name is introduced in two namespaces in two scopes,
/// we use the position of the first scope. /// we use the position of the first scope.
pub fn names_in_scope(&self, db: &dyn DefDatabase) -> IndexMap<Name, SmallVec<[ScopeDef; 1]>> { pub fn names_in_scope(
&self,
db: &dyn DefDatabase,
) -> FxIndexMap<Name, SmallVec<[ScopeDef; 1]>> {
let mut res = ScopeNames::default(); let mut res = ScopeNames::default();
for scope in self.scopes() { for scope in self.scopes() {
scope.process_names(db, &mut res); scope.process_names(&mut res, db);
} }
res.map res.map
} }
@ -475,7 +478,7 @@ impl Resolver {
} }
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ScopeDef { pub enum ScopeDef {
ModuleDef(ModuleDefId), ModuleDef(ModuleDefId),
Unknown, Unknown,
@ -487,7 +490,7 @@ pub enum ScopeDef {
} }
impl Scope { impl Scope {
fn process_names(&self, db: &dyn DefDatabase, acc: &mut ScopeNames) { fn process_names(&self, acc: &mut ScopeNames, db: &dyn DefDatabase) {
match self { match self {
Scope::ModuleScope(m) => { Scope::ModuleScope(m) => {
// FIXME: should we provide `self` here? // FIXME: should we provide `self` here?
@ -700,9 +703,10 @@ fn to_type_ns(per_ns: PerNs) -> Option<TypeNs> {
Some(res) Some(res)
} }
type FxIndexMap<K, V> = IndexMap<K, V, BuildHasherDefault<rustc_hash::FxHasher>>;
#[derive(Default)] #[derive(Default)]
struct ScopeNames { struct ScopeNames {
map: IndexMap<Name, SmallVec<[ScopeDef; 1]>>, map: FxIndexMap<Name, SmallVec<[ScopeDef; 1]>>,
} }
impl ScopeNames { impl ScopeNames {

View File

@ -30,7 +30,7 @@ pub(crate) fn complete_lifetime(acc: &mut Completions, ctx: &CompletionContext)
let param_lifetime = param_lifetime.as_ref().map(ast::Lifetime::text); let param_lifetime = param_lifetime.as_ref().map(ast::Lifetime::text);
let param_lifetime = param_lifetime.as_ref().map(TokenText::as_str); let param_lifetime = param_lifetime.as_ref().map(TokenText::as_str);
ctx.scope.process_all_names(&mut |name, res| { ctx.process_all_names_raw(&mut |name, res| {
if matches!( if matches!(
res, res,
ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_))
@ -49,7 +49,7 @@ pub(crate) fn complete_label(acc: &mut Completions, ctx: &CompletionContext) {
if !matches!(ctx.lifetime_ctx, Some(LifetimeContext::LabelRef)) { if !matches!(ctx.lifetime_ctx, Some(LifetimeContext::LabelRef)) {
return; return;
} }
ctx.scope.process_all_names(&mut |name, res| { ctx.process_all_names_raw(&mut |name, res| {
if let ScopeDef::Label(_) = res { if let ScopeDef::Label(_) = res {
acc.add_label(ctx, name); acc.add_label(ctx, name);
} }

View File

@ -12,7 +12,7 @@ use ide_db::{
famous_defs::FamousDefs, famous_defs::FamousDefs,
RootDatabase, RootDatabase,
}; };
use rustc_hash::FxHashSet; use rustc_hash::{FxHashMap, FxHashSet};
use syntax::{ use syntax::{
algo::{find_node_at_offset, non_trivia_sibling}, algo::{find_node_at_offset, non_trivia_sibling},
ast::{self, AttrKind, HasName, NameOrNameRef}, ast::{self, AttrKind, HasName, NameOrNameRef},
@ -146,7 +146,7 @@ pub(crate) struct CompletionContext<'a> {
pub(super) existing_derives: FxHashSet<hir::Macro>, pub(super) existing_derives: FxHashSet<hir::Macro>,
pub(super) locals: Vec<(Name, Local)>, pub(super) locals: FxHashMap<Name, Local>,
} }
impl<'a> CompletionContext<'a> { impl<'a> CompletionContext<'a> {
@ -293,6 +293,10 @@ impl<'a> CompletionContext<'a> {
self.path_context.as_ref().and_then(|it| it.kind) self.path_context.as_ref().and_then(|it| it.kind)
} }
pub(crate) fn is_immediately_after_macro_bang(&self) -> bool {
self.token.kind() == BANG && self.token.parent().map_or(false, |it| it.kind() == MACRO_CALL)
}
/// Checks if an item is visible and not `doc(hidden)` at the completion site. /// Checks if an item is visible and not `doc(hidden)` at the completion site.
pub(crate) fn is_visible<I>(&self, item: &I) -> Visible pub(crate) fn is_visible<I>(&self, item: &I) -> Visible
where where
@ -318,11 +322,6 @@ impl<'a> CompletionContext<'a> {
_ => false, _ => false,
} }
} }
pub(crate) fn is_immediately_after_macro_bang(&self) -> bool {
self.token.kind() == BANG && self.token.parent().map_or(false, |it| it.kind() == MACRO_CALL)
}
/// Whether the given trait is an operator trait or not. /// Whether the given trait is an operator trait or not.
pub(crate) fn is_ops_trait(&self, trait_: hir::Trait) -> bool { pub(crate) fn is_ops_trait(&self, trait_: hir::Trait) -> bool {
match trait_.attrs(self.db).lang() { match trait_.attrs(self.db).lang() {
@ -340,7 +339,12 @@ impl<'a> CompletionContext<'a> {
} }
f(name, def); f(name, def);
}) });
}
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));
} }
fn is_visible_impl( fn is_visible_impl(
@ -372,16 +376,11 @@ impl<'a> CompletionContext<'a> {
} }
fn is_doc_hidden(&self, attrs: &hir::Attrs, defining_crate: hir::Crate) -> bool { fn is_doc_hidden(&self, attrs: &hir::Attrs, defining_crate: hir::Crate) -> bool {
let krate = match self.krate { match self.krate {
Some(it) => it,
None => return true,
};
if krate != defining_crate && attrs.has_doc_hidden() {
// `doc(hidden)` items are only completed within the defining crate. // `doc(hidden)` items are only completed within the defining crate.
return true; Some(krate) => krate != defining_crate && attrs.has_doc_hidden(),
None => true,
} }
false
} }
} }
@ -413,10 +412,10 @@ impl<'a> CompletionContext<'a> {
let scope = sema.scope_at_offset(&token.parent()?, offset); let scope = sema.scope_at_offset(&token.parent()?, offset);
let krate = scope.krate(); let krate = scope.krate();
let module = scope.module(); let module = scope.module();
let mut locals = vec![]; let mut locals = FxHashMap::default();
scope.process_all_names(&mut |name, scope| { scope.process_all_names(&mut |name, scope| {
if let ScopeDef::Local(local) = scope { if let ScopeDef::Local(local) = scope {
locals.push((name, local)); locals.insert(name, local);
} }
}); });