mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 11:20:54 +00:00
Merge pull request #19375 from ChayimFriedman2/do-not-complete
feat: Allow crate authors to control completion of their things
This commit is contained in:
commit
2e1ff255ae
@ -12,7 +12,7 @@ use crate::{
|
||||
ConstId, ExternCrateId, FunctionId, HasModule, ImplId, ItemContainerId, ItemLoc, Lookup,
|
||||
Macro2Id, MacroRulesId, ProcMacroId, StaticId, TraitAliasId, TraitId, TypeAliasId,
|
||||
db::DefDatabase,
|
||||
item_tree::{self, FnFlags, ModItem},
|
||||
item_tree::{self, FnFlags, ModItem, StaticFlags},
|
||||
nameres::proc_macro::{ProcMacroKind, parse_macro_name_and_helper_attrs},
|
||||
path::ImportAlias,
|
||||
type_ref::{TraitRef, TypeBound, TypeRefId, TypesMap},
|
||||
@ -27,9 +27,8 @@ pub struct FunctionData {
|
||||
pub visibility: RawVisibility,
|
||||
pub abi: Option<Symbol>,
|
||||
pub legacy_const_generics_indices: Option<Box<Box<[u32]>>>,
|
||||
pub rustc_allow_incoherent_impl: bool,
|
||||
pub types_map: Arc<TypesMap>,
|
||||
flags: FnFlags,
|
||||
pub flags: FnFlags,
|
||||
}
|
||||
|
||||
impl FunctionData {
|
||||
@ -72,7 +71,9 @@ impl FunctionData {
|
||||
}
|
||||
|
||||
let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into());
|
||||
let rustc_allow_incoherent_impl = attrs.by_key(&sym::rustc_allow_incoherent_impl).exists();
|
||||
if attrs.by_key(&sym::rustc_allow_incoherent_impl).exists() {
|
||||
flags |= FnFlags::RUSTC_ALLOW_INCOHERENT_IMPL;
|
||||
}
|
||||
if flags.contains(FnFlags::HAS_UNSAFE_KW)
|
||||
&& attrs.by_key(&sym::rustc_deprecated_safe_2024).exists()
|
||||
{
|
||||
@ -101,51 +102,65 @@ impl FunctionData {
|
||||
legacy_const_generics_indices: attrs.rustc_legacy_const_generics(),
|
||||
types_map: func.types_map.clone(),
|
||||
flags,
|
||||
rustc_allow_incoherent_impl,
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn has_body(&self) -> bool {
|
||||
self.flags.contains(FnFlags::HAS_BODY)
|
||||
}
|
||||
|
||||
/// True if the first param is `self`. This is relevant to decide whether this
|
||||
/// can be called as a method.
|
||||
#[inline]
|
||||
pub fn has_self_param(&self) -> bool {
|
||||
self.flags.contains(FnFlags::HAS_SELF_PARAM)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_default(&self) -> bool {
|
||||
self.flags.contains(FnFlags::HAS_DEFAULT_KW)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_const(&self) -> bool {
|
||||
self.flags.contains(FnFlags::HAS_CONST_KW)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_async(&self) -> bool {
|
||||
self.flags.contains(FnFlags::HAS_ASYNC_KW)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_unsafe(&self) -> bool {
|
||||
self.flags.contains(FnFlags::HAS_UNSAFE_KW)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_deprecated_safe_2024(&self) -> bool {
|
||||
self.flags.contains(FnFlags::DEPRECATED_SAFE_2024)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_safe(&self) -> bool {
|
||||
self.flags.contains(FnFlags::HAS_SAFE_KW)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_varargs(&self) -> bool {
|
||||
self.flags.contains(FnFlags::IS_VARARGS)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn has_target_feature(&self) -> bool {
|
||||
self.flags.contains(FnFlags::HAS_TARGET_FEATURE)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn rustc_allow_incoherent_impl(&self) -> bool {
|
||||
self.flags.contains(FnFlags::RUSTC_ALLOW_INCOHERENT_IMPL)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
@ -153,15 +168,37 @@ pub struct TypeAliasData {
|
||||
pub name: Name,
|
||||
pub type_ref: Option<TypeRefId>,
|
||||
pub visibility: RawVisibility,
|
||||
pub is_extern: bool,
|
||||
pub rustc_has_incoherent_inherent_impls: bool,
|
||||
pub rustc_allow_incoherent_impl: bool,
|
||||
pub flags: TypeAliasFlags,
|
||||
/// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl).
|
||||
pub bounds: Box<[TypeBound]>,
|
||||
pub types_map: Arc<TypesMap>,
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TypeAliasFlags: u8 {
|
||||
const IS_EXTERN = 1 << 0;
|
||||
const RUSTC_HAS_INCOHERENT_INHERENT_IMPLS = 1 << 1;
|
||||
const RUSTC_ALLOW_INCOHERENT_IMPL = 1 << 2;
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeAliasData {
|
||||
#[inline]
|
||||
pub fn is_extern(&self) -> bool {
|
||||
self.flags.contains(TypeAliasFlags::IS_EXTERN)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn rustc_has_incoherent_inherent_impls(&self) -> bool {
|
||||
self.flags.contains(TypeAliasFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn rustc_allow_incoherent_impl(&self) -> bool {
|
||||
self.flags.contains(TypeAliasFlags::RUSTC_ALLOW_INCOHERENT_IMPL)
|
||||
}
|
||||
|
||||
pub(crate) fn type_alias_data_query(
|
||||
db: &dyn DefDatabase,
|
||||
typ: TypeAliasId,
|
||||
@ -180,17 +217,24 @@ impl TypeAliasData {
|
||||
loc.container.module(db).krate(),
|
||||
ModItem::from(loc.id.value).into(),
|
||||
);
|
||||
let rustc_has_incoherent_inherent_impls =
|
||||
attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists();
|
||||
let rustc_allow_incoherent_impl = attrs.by_key(&sym::rustc_allow_incoherent_impl).exists();
|
||||
|
||||
let mut flags = TypeAliasFlags::empty();
|
||||
|
||||
if matches!(loc.container, ItemContainerId::ExternBlockId(_)) {
|
||||
flags |= TypeAliasFlags::IS_EXTERN;
|
||||
}
|
||||
if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() {
|
||||
flags |= TypeAliasFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS;
|
||||
}
|
||||
if attrs.by_key(&sym::rustc_allow_incoherent_impl).exists() {
|
||||
flags |= TypeAliasFlags::RUSTC_ALLOW_INCOHERENT_IMPL;
|
||||
}
|
||||
|
||||
Arc::new(TypeAliasData {
|
||||
name: typ.name.clone(),
|
||||
type_ref: typ.type_ref,
|
||||
visibility,
|
||||
is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)),
|
||||
rustc_has_incoherent_inherent_impls,
|
||||
rustc_allow_incoherent_impl,
|
||||
flags,
|
||||
bounds: typ.bounds.clone(),
|
||||
types_map: typ.types_map.clone(),
|
||||
})
|
||||
@ -199,7 +243,7 @@ impl TypeAliasData {
|
||||
|
||||
bitflags::bitflags! {
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
|
||||
pub struct TraitFlags: u8 {
|
||||
pub struct TraitFlags: u16 {
|
||||
const IS_AUTO = 1 << 0;
|
||||
const IS_UNSAFE = 1 << 1;
|
||||
const IS_FUNDAMENTAL = 1 << 2;
|
||||
@ -332,9 +376,9 @@ impl Macro2Data {
|
||||
let loc = makro.lookup(db);
|
||||
let item_tree = loc.id.item_tree(db);
|
||||
let makro = &item_tree[loc.id.value];
|
||||
let attrs = item_tree.attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into());
|
||||
|
||||
let helpers = item_tree
|
||||
.attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into())
|
||||
let helpers = attrs
|
||||
.by_key(&sym::rustc_builtin_macro)
|
||||
.tt_values()
|
||||
.next()
|
||||
@ -362,11 +406,9 @@ impl MacroRulesData {
|
||||
let loc = makro.lookup(db);
|
||||
let item_tree = loc.id.item_tree(db);
|
||||
let makro = &item_tree[loc.id.value];
|
||||
let attrs = item_tree.attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into());
|
||||
|
||||
let macro_export = item_tree
|
||||
.attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into())
|
||||
.by_key(&sym::macro_export)
|
||||
.exists();
|
||||
let macro_export = attrs.by_key(&sym::macro_export).exists();
|
||||
|
||||
Arc::new(MacroRulesData { name: makro.name.clone(), macro_export })
|
||||
}
|
||||
@ -387,11 +429,9 @@ impl ProcMacroData {
|
||||
let loc = makro.lookup(db);
|
||||
let item_tree = loc.id.item_tree(db);
|
||||
let makro = &item_tree[loc.id.value];
|
||||
let attrs = item_tree.attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into());
|
||||
|
||||
let (name, helpers) = if let Some(def) = item_tree
|
||||
.attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into())
|
||||
.parse_proc_macro_decl(&makro.name)
|
||||
{
|
||||
let (name, helpers) = if let Some(def) = attrs.parse_proc_macro_decl(&makro.name) {
|
||||
(
|
||||
def.name,
|
||||
match def.kind {
|
||||
@ -404,6 +444,7 @@ impl ProcMacroData {
|
||||
stdx::never!("proc macro declaration is not a proc macro");
|
||||
(makro.name.clone(), None)
|
||||
};
|
||||
|
||||
Arc::new(ProcMacroData { name, helpers })
|
||||
}
|
||||
}
|
||||
@ -450,9 +491,16 @@ pub struct ConstData {
|
||||
pub name: Option<Name>,
|
||||
pub type_ref: TypeRefId,
|
||||
pub visibility: RawVisibility,
|
||||
pub rustc_allow_incoherent_impl: bool,
|
||||
pub has_body: bool,
|
||||
pub types_map: Arc<TypesMap>,
|
||||
pub flags: ConstFlags,
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct ConstFlags: u8 {
|
||||
const RUSTC_ALLOW_INCOHERENT_IMPL = 1 << 0;
|
||||
const HAS_BODY = 1 << 1;
|
||||
}
|
||||
}
|
||||
|
||||
impl ConstData {
|
||||
@ -465,21 +513,38 @@ impl ConstData {
|
||||
} else {
|
||||
item_tree[konst.visibility].clone()
|
||||
};
|
||||
let attrs = item_tree.attrs(
|
||||
db,
|
||||
loc.container.module(db).krate(),
|
||||
ModItem::from(loc.id.value).into(),
|
||||
);
|
||||
|
||||
let rustc_allow_incoherent_impl = item_tree
|
||||
.attrs(db, loc.container.module(db).krate(), ModItem::from(loc.id.value).into())
|
||||
.by_key(&sym::rustc_allow_incoherent_impl)
|
||||
.exists();
|
||||
let mut flags = ConstFlags::empty();
|
||||
if attrs.by_key(&sym::rustc_allow_incoherent_impl).exists() {
|
||||
flags |= ConstFlags::RUSTC_ALLOW_INCOHERENT_IMPL;
|
||||
}
|
||||
if konst.has_body {
|
||||
flags |= ConstFlags::HAS_BODY;
|
||||
}
|
||||
|
||||
Arc::new(ConstData {
|
||||
name: konst.name.clone(),
|
||||
type_ref: konst.type_ref,
|
||||
visibility,
|
||||
rustc_allow_incoherent_impl,
|
||||
has_body: konst.has_body,
|
||||
flags,
|
||||
types_map: konst.types_map.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn rustc_allow_incoherent_impl(&self) -> bool {
|
||||
self.flags.contains(ConstFlags::RUSTC_ALLOW_INCOHERENT_IMPL)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn has_body(&self) -> bool {
|
||||
self.flags.contains(ConstFlags::HAS_BODY)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
@ -487,11 +552,8 @@ pub struct StaticData {
|
||||
pub name: Name,
|
||||
pub type_ref: TypeRefId,
|
||||
pub visibility: RawVisibility,
|
||||
pub mutable: bool,
|
||||
pub is_extern: bool,
|
||||
pub has_safe_kw: bool,
|
||||
pub has_unsafe_kw: bool,
|
||||
pub types_map: Arc<TypesMap>,
|
||||
pub flags: StaticFlags,
|
||||
}
|
||||
|
||||
impl StaticData {
|
||||
@ -500,17 +562,39 @@ impl StaticData {
|
||||
let item_tree = loc.id.item_tree(db);
|
||||
let statik = &item_tree[loc.id.value];
|
||||
|
||||
let mut flags = statik.flags;
|
||||
if matches!(loc.container, ItemContainerId::ExternBlockId(_)) {
|
||||
flags |= StaticFlags::IS_EXTERN;
|
||||
}
|
||||
|
||||
Arc::new(StaticData {
|
||||
name: statik.name.clone(),
|
||||
type_ref: statik.type_ref,
|
||||
visibility: item_tree[statik.visibility].clone(),
|
||||
mutable: statik.mutable,
|
||||
is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)),
|
||||
has_safe_kw: statik.has_safe_kw,
|
||||
has_unsafe_kw: statik.has_unsafe_kw,
|
||||
flags,
|
||||
types_map: statik.types_map.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_extern(&self) -> bool {
|
||||
self.flags.contains(StaticFlags::IS_EXTERN)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn mutable(&self) -> bool {
|
||||
self.flags.contains(StaticFlags::MUTABLE)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn has_safe_kw(&self) -> bool {
|
||||
self.flags.contains(StaticFlags::HAS_SAFE_KW)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn has_unsafe_kw(&self) -> bool {
|
||||
self.flags.contains(StaticFlags::HAS_UNSAFE_KW)
|
||||
}
|
||||
}
|
||||
|
||||
fn trait_vis(db: &dyn DefDatabase, trait_id: TraitId) -> RawVisibility {
|
||||
|
@ -226,6 +226,7 @@ impl StructData {
|
||||
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
|
||||
let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into());
|
||||
let mut flags = StructFlags::NO_FLAGS;
|
||||
|
||||
if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() {
|
||||
flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL;
|
||||
}
|
||||
@ -290,10 +291,10 @@ impl EnumData {
|
||||
let krate = loc.container.krate;
|
||||
let item_tree = loc.id.item_tree(db);
|
||||
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
|
||||
let rustc_has_incoherent_inherent_impls = item_tree
|
||||
.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into())
|
||||
.by_key(&sym::rustc_has_incoherent_inherent_impls)
|
||||
.exists();
|
||||
let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into());
|
||||
|
||||
let rustc_has_incoherent_inherent_impls =
|
||||
attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists();
|
||||
|
||||
let enum_ = &item_tree[loc.id.value];
|
||||
|
||||
|
@ -9,11 +9,11 @@ use itertools::Itertools;
|
||||
use rustc_hash::FxHashSet;
|
||||
use smallvec::SmallVec;
|
||||
use span::Edition;
|
||||
use stdx::{TupleExt, format_to};
|
||||
use stdx::format_to;
|
||||
use triomphe::Arc;
|
||||
|
||||
use crate::{
|
||||
AssocItemId, FxIndexMap, ModuleDefId, ModuleId, TraitId,
|
||||
AssocItemId, AttrDefId, Complete, FxIndexMap, ModuleDefId, ModuleId, TraitId,
|
||||
db::DefDatabase,
|
||||
item_scope::{ImportOrExternCrate, ItemInNs},
|
||||
nameres::DefMap,
|
||||
@ -31,6 +31,8 @@ pub struct ImportInfo {
|
||||
pub is_doc_hidden: bool,
|
||||
/// Whether this item is annotated with `#[unstable(..)]`.
|
||||
pub is_unstable: bool,
|
||||
/// The value of `#[rust_analyzer::completions(...)]`, if exists.
|
||||
pub complete: Complete,
|
||||
}
|
||||
|
||||
/// A map from publicly exported items to its name.
|
||||
@ -172,16 +174,22 @@ impl ImportMap {
|
||||
ItemInNs::Macros(id) => Some(id.into()),
|
||||
}
|
||||
};
|
||||
let (is_doc_hidden, is_unstable) = attr_id.map_or((false, false), |attr_id| {
|
||||
let attrs = db.attrs(attr_id);
|
||||
(attrs.has_doc_hidden(), attrs.is_unstable())
|
||||
});
|
||||
let (is_doc_hidden, is_unstable, do_not_complete) = match attr_id {
|
||||
None => (false, false, Complete::Yes),
|
||||
Some(attr_id) => {
|
||||
let attrs = db.attrs(attr_id);
|
||||
let do_not_complete =
|
||||
Complete::extract(matches!(attr_id, AttrDefId::TraitId(_)), &attrs);
|
||||
(attrs.has_doc_hidden(), attrs.is_unstable(), do_not_complete)
|
||||
}
|
||||
};
|
||||
|
||||
let import_info = ImportInfo {
|
||||
name: name.clone(),
|
||||
container: module,
|
||||
is_doc_hidden,
|
||||
is_unstable,
|
||||
complete: do_not_complete,
|
||||
};
|
||||
|
||||
if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() {
|
||||
@ -235,12 +243,17 @@ impl ImportMap {
|
||||
ItemInNs::Values(module_def_id)
|
||||
};
|
||||
|
||||
let attrs = &db.attrs(item.into());
|
||||
let attr_id = item.into();
|
||||
let attrs = &db.attrs(attr_id);
|
||||
let item_do_not_complete = Complete::extract(false, attrs);
|
||||
let do_not_complete =
|
||||
Complete::for_trait_item(trait_import_info.complete, item_do_not_complete);
|
||||
let assoc_item_info = ImportInfo {
|
||||
container: trait_import_info.container,
|
||||
name: assoc_item_name.clone(),
|
||||
is_doc_hidden: attrs.has_doc_hidden(),
|
||||
is_unstable: attrs.is_unstable(),
|
||||
complete: do_not_complete,
|
||||
};
|
||||
|
||||
let (infos, _) =
|
||||
@ -398,7 +411,7 @@ pub fn search_dependencies(
|
||||
db: &dyn DefDatabase,
|
||||
krate: Crate,
|
||||
query: &Query,
|
||||
) -> FxHashSet<ItemInNs> {
|
||||
) -> FxHashSet<(ItemInNs, Complete)> {
|
||||
let _p = tracing::info_span!("search_dependencies", ?query).entered();
|
||||
|
||||
let import_maps: Vec<_> =
|
||||
@ -439,7 +452,7 @@ fn search_maps(
|
||||
import_maps: &[Arc<ImportMap>],
|
||||
mut stream: fst::map::Union<'_>,
|
||||
query: &Query,
|
||||
) -> FxHashSet<ItemInNs> {
|
||||
) -> FxHashSet<(ItemInNs, Complete)> {
|
||||
let mut res = FxHashSet::default();
|
||||
while let Some((_, indexed_values)) = stream.next() {
|
||||
for &IndexedValue { index: import_map_idx, value } in indexed_values {
|
||||
@ -459,8 +472,9 @@ fn search_maps(
|
||||
})
|
||||
.filter(|&(_, info)| {
|
||||
query.search_mode.check(&query.query, query.case_sensitive, info.name.as_str())
|
||||
});
|
||||
res.extend(iter.map(TupleExt::head));
|
||||
})
|
||||
.map(|(item, import_info)| (item, import_info.complete));
|
||||
res.extend(iter);
|
||||
}
|
||||
}
|
||||
|
||||
@ -521,7 +535,7 @@ mod tests {
|
||||
|
||||
let actual = search_dependencies(db.upcast(), krate, &query)
|
||||
.into_iter()
|
||||
.filter_map(|dependency| {
|
||||
.filter_map(|(dependency, _)| {
|
||||
let dependency_krate = dependency.krate(db.upcast())?;
|
||||
let dependency_imports = db.import_map(dependency_krate);
|
||||
|
||||
|
@ -358,7 +358,7 @@ impl ItemScope {
|
||||
}
|
||||
|
||||
/// Get a name from current module scope, legacy macros are not included
|
||||
pub(crate) fn get(&self, name: &Name) -> PerNs {
|
||||
pub fn get(&self, name: &Name) -> PerNs {
|
||||
PerNs {
|
||||
types: self.types.get(name).copied(),
|
||||
values: self.values.get(name).copied(),
|
||||
|
@ -962,7 +962,7 @@ pub struct Param {
|
||||
|
||||
bitflags::bitflags! {
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
|
||||
pub(crate) struct FnFlags: u16 {
|
||||
pub struct FnFlags: u16 {
|
||||
const HAS_SELF_PARAM = 1 << 0;
|
||||
const HAS_BODY = 1 << 1;
|
||||
const HAS_DEFAULT_KW = 1 << 2;
|
||||
@ -977,6 +977,7 @@ bitflags::bitflags! {
|
||||
/// it if needed.
|
||||
const HAS_TARGET_FEATURE = 1 << 8;
|
||||
const DEPRECATED_SAFE_2024 = 1 << 9;
|
||||
const RUSTC_ALLOW_INCOHERENT_IMPL = 1 << 10;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1050,15 +1051,22 @@ pub struct Const {
|
||||
pub struct Static {
|
||||
pub name: Name,
|
||||
pub visibility: RawVisibilityId,
|
||||
// TODO: use bitflags when we have more flags
|
||||
pub mutable: bool,
|
||||
pub has_safe_kw: bool,
|
||||
pub has_unsafe_kw: bool,
|
||||
pub flags: StaticFlags,
|
||||
pub type_ref: TypeRefId,
|
||||
pub ast_id: FileAstId<ast::Static>,
|
||||
pub types_map: Arc<TypesMap>,
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct StaticFlags: u8 {
|
||||
const MUTABLE = 1 << 0;
|
||||
const IS_EXTERN = 1 << 1;
|
||||
const HAS_SAFE_KW = 1 << 2;
|
||||
const HAS_UNSAFE_KW = 1 << 3;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Trait {
|
||||
pub name: Name,
|
||||
|
@ -29,8 +29,8 @@ use crate::{
|
||||
GenericModItem, Idx, Impl, ImportAlias, Interned, ItemTree, ItemTreeData,
|
||||
ItemTreeSourceMaps, ItemTreeSourceMapsBuilder, Macro2, MacroCall, MacroRules, Mod, ModItem,
|
||||
ModKind, ModPath, Mutability, Name, Param, Path, Range, RawAttrs, RawIdx, RawVisibilityId,
|
||||
Static, Struct, StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind,
|
||||
Variant,
|
||||
Static, StaticFlags, Struct, StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree,
|
||||
UseTreeKind, Variant,
|
||||
},
|
||||
lower::LowerCtx,
|
||||
path::AssociatedTypeBinding,
|
||||
@ -620,22 +620,23 @@ impl<'a> Ctx<'a> {
|
||||
let name = static_.name()?.as_name();
|
||||
let type_ref = TypeRef::from_ast_opt(&mut body_ctx, static_.ty());
|
||||
let visibility = self.lower_visibility(static_);
|
||||
let mutable = static_.mut_token().is_some();
|
||||
let has_safe_kw = static_.safe_token().is_some();
|
||||
let has_unsafe_kw = static_.unsafe_token().is_some();
|
||||
|
||||
let mut flags = StaticFlags::empty();
|
||||
if static_.mut_token().is_some() {
|
||||
flags |= StaticFlags::MUTABLE;
|
||||
}
|
||||
if static_.safe_token().is_some() {
|
||||
flags |= StaticFlags::HAS_SAFE_KW;
|
||||
}
|
||||
if static_.unsafe_token().is_some() {
|
||||
flags |= StaticFlags::HAS_UNSAFE_KW;
|
||||
}
|
||||
|
||||
let ast_id = self.source_ast_id_map.ast_id(static_);
|
||||
types_map.shrink_to_fit();
|
||||
types_source_map.shrink_to_fit();
|
||||
let res = Static {
|
||||
name,
|
||||
visibility,
|
||||
mutable,
|
||||
type_ref,
|
||||
ast_id,
|
||||
has_safe_kw,
|
||||
has_unsafe_kw,
|
||||
types_map: Arc::new(types_map),
|
||||
};
|
||||
let res =
|
||||
Static { name, visibility, type_ref, ast_id, flags, types_map: Arc::new(types_map) };
|
||||
self.source_maps.statics.push(types_source_map);
|
||||
Some(id(self.data().statics.alloc(res)))
|
||||
}
|
||||
|
@ -11,8 +11,8 @@ use crate::{
|
||||
AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, Field, FieldParent,
|
||||
FieldsShape, FileItemTreeId, FnFlags, Function, GenericModItem, GenericParams, Impl,
|
||||
ItemTree, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, Param, Path, RawAttrs,
|
||||
RawVisibilityId, Static, Struct, Trait, TraitAlias, TypeAlias, TypeBound, Union, Use,
|
||||
UseTree, UseTreeKind, Variant,
|
||||
RawVisibilityId, Static, StaticFlags, Struct, Trait, TraitAlias, TypeAlias, TypeBound,
|
||||
Union, Use, UseTree, UseTreeKind, Variant,
|
||||
},
|
||||
pretty::{print_path, print_type_bounds, print_type_ref},
|
||||
type_ref::{TypeRefId, TypesMap},
|
||||
@ -418,26 +418,18 @@ impl Printer<'_> {
|
||||
wln!(self, " = _;");
|
||||
}
|
||||
ModItem::Static(it) => {
|
||||
let Static {
|
||||
name,
|
||||
visibility,
|
||||
mutable,
|
||||
type_ref,
|
||||
ast_id,
|
||||
has_safe_kw,
|
||||
has_unsafe_kw,
|
||||
types_map,
|
||||
} = &self.tree[it];
|
||||
let Static { name, visibility, type_ref, ast_id, types_map, flags } =
|
||||
&self.tree[it];
|
||||
self.print_ast_id(ast_id.erase());
|
||||
self.print_visibility(*visibility);
|
||||
if *has_safe_kw {
|
||||
if flags.contains(StaticFlags::HAS_SAFE_KW) {
|
||||
w!(self, "safe ");
|
||||
}
|
||||
if *has_unsafe_kw {
|
||||
if flags.contains(StaticFlags::HAS_UNSAFE_KW) {
|
||||
w!(self, "unsafe ");
|
||||
}
|
||||
w!(self, "static ");
|
||||
if *mutable {
|
||||
if flags.contains(StaticFlags::MUTABLE) {
|
||||
w!(self, "mut ");
|
||||
}
|
||||
w!(self, "{}: ", name.display(self.db.upcast(), self.edition));
|
||||
|
@ -53,7 +53,7 @@ pub mod find_path;
|
||||
pub mod import_map;
|
||||
pub mod visibility;
|
||||
|
||||
use intern::Interned;
|
||||
use intern::{Interned, sym};
|
||||
pub use rustc_abi as layout;
|
||||
use triomphe::Arc;
|
||||
|
||||
@ -86,6 +86,7 @@ use syntax::{AstNode, ast};
|
||||
pub use hir_expand::{Intern, Lookup, tt};
|
||||
|
||||
use crate::{
|
||||
attr::Attrs,
|
||||
builtin_type::BuiltinType,
|
||||
data::adt::VariantData,
|
||||
db::DefDatabase,
|
||||
@ -1502,3 +1503,81 @@ pub struct UnresolvedMacro {
|
||||
|
||||
#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
|
||||
pub struct SyntheticSyntax;
|
||||
|
||||
// Feature: Completions Attribute
|
||||
// Crate authors can opt their type out of completions in some cases.
|
||||
// This is done with the `#[rust_analyzer::completions(...)]` attribute.
|
||||
//
|
||||
// All completeable things support `#[rust_analyzer::completions(ignore_flyimport)]`,
|
||||
// which causes the thing to get excluded from flyimport completion. It will still
|
||||
// be completed when in scope. This is analogous to the setting `rust-analyzer.completion.autoimport.exclude`
|
||||
// with `"type": "always"`.
|
||||
//
|
||||
// In addition, traits support two more modes: `#[rust_analyzer::completions(ignore_flyimport_methods)]`,
|
||||
// which means the trait itself may still be flyimported but its methods won't, and
|
||||
// `#[rust_analyzer::completions(ignore_methods)]`, which means the methods won't be completed even when
|
||||
// the trait is in scope (but the trait itself may still be completed). The methods will still be completed
|
||||
// on `dyn Trait`, `impl Trait` or where the trait is specified in bounds. These modes correspond to
|
||||
// the settings `rust-analyzer.completion.autoimport.exclude` with `"type": "methods"` and
|
||||
// `rust-analyzer.completion.excludeTraits`, respectively.
|
||||
//
|
||||
// Malformed attributes will be ignored without warnings.
|
||||
//
|
||||
// Note that users have no way to override this attribute, so be careful and only include things
|
||||
// users definitely do not want to be completed!
|
||||
|
||||
/// `#[rust_analyzer::completions(...)]` options.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum Complete {
|
||||
/// No `#[rust_analyzer::completions(...)]`.
|
||||
Yes,
|
||||
/// `#[rust_analyzer::completions(ignore_flyimport)]`.
|
||||
IgnoreFlyimport,
|
||||
/// `#[rust_analyzer::completions(ignore_flyimport_methods)]` (on a trait only).
|
||||
IgnoreFlyimportMethods,
|
||||
/// `#[rust_analyzer::completions(ignore_methods)]` (on a trait only).
|
||||
IgnoreMethods,
|
||||
}
|
||||
|
||||
impl Complete {
|
||||
pub fn extract(is_trait: bool, attrs: &Attrs) -> Complete {
|
||||
let mut do_not_complete = Complete::Yes;
|
||||
for ra_attr in attrs.rust_analyzer_tool() {
|
||||
let segments = ra_attr.path.segments();
|
||||
if segments.len() != 2 {
|
||||
continue;
|
||||
}
|
||||
let action = segments[1].symbol();
|
||||
if *action == sym::completions {
|
||||
match ra_attr.token_tree_value().map(|tt| tt.token_trees().flat_tokens()) {
|
||||
Some([tt::TokenTree::Leaf(tt::Leaf::Ident(ident))]) => {
|
||||
if ident.sym == sym::ignore_flyimport {
|
||||
do_not_complete = Complete::IgnoreFlyimport;
|
||||
} else if is_trait {
|
||||
if ident.sym == sym::ignore_methods {
|
||||
do_not_complete = Complete::IgnoreMethods;
|
||||
} else if ident.sym == sym::ignore_flyimport_methods {
|
||||
do_not_complete = Complete::IgnoreFlyimportMethods;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
do_not_complete
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn for_trait_item(trait_attr: Complete, item_attr: Complete) -> Complete {
|
||||
match (trait_attr, item_attr) {
|
||||
(
|
||||
Complete::IgnoreFlyimportMethods
|
||||
| Complete::IgnoreFlyimport
|
||||
| Complete::IgnoreMethods,
|
||||
_,
|
||||
) => Complete::IgnoreFlyimport,
|
||||
_ => item_attr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -558,7 +558,7 @@ impl<'a> DeclValidator<'a> {
|
||||
|
||||
fn validate_static(&mut self, static_id: StaticId) {
|
||||
let data = self.db.static_data(static_id);
|
||||
if data.is_extern {
|
||||
if data.is_extern() {
|
||||
cov_mark::hit!(extern_static_incorrect_case_ignored);
|
||||
return;
|
||||
}
|
||||
|
@ -362,9 +362,9 @@ impl<'a> UnsafeVisitor<'a> {
|
||||
self.resolver.resolve_path_in_value_ns(self.db.upcast(), path, hygiene);
|
||||
if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id), _)) = value_or_partial {
|
||||
let static_data = self.db.static_data(id);
|
||||
if static_data.mutable {
|
||||
if static_data.mutable() {
|
||||
self.on_unsafe_op(node, UnsafetyReason::MutableStatic);
|
||||
} else if static_data.is_extern && !static_data.has_safe_kw {
|
||||
} else if static_data.is_extern() && !static_data.has_safe_kw() {
|
||||
self.on_unsafe_op(node, UnsafetyReason::ExternStatic);
|
||||
}
|
||||
}
|
||||
|
@ -1577,7 +1577,7 @@ pub(crate) fn type_for_type_alias_with_diagnostics_query(
|
||||
let mut ctx = TyLoweringContext::new(db, &resolver, &type_alias_data.types_map, t.into())
|
||||
.with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
|
||||
.with_type_param_mode(ParamLoweringMode::Variable);
|
||||
let inner = if type_alias_data.is_extern {
|
||||
let inner = if type_alias_data.is_extern() {
|
||||
TyKind::Foreign(crate::to_foreign_def_id(t)).intern(Interner)
|
||||
} else {
|
||||
type_alias_data
|
||||
|
@ -401,7 +401,7 @@ pub fn def_crates(db: &dyn HirDatabase, ty: &Ty, cur_crate: Crate) -> Option<Sma
|
||||
}
|
||||
&TyKind::Foreign(id) => {
|
||||
let alias = from_foreign_def_id(id);
|
||||
Some(if db.type_alias_data(alias).rustc_has_incoherent_inherent_impls {
|
||||
Some(if db.type_alias_data(alias).rustc_has_incoherent_inherent_impls() {
|
||||
db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::ForeignType(id))
|
||||
} else {
|
||||
smallvec![alias.module(db.upcast()).krate()]
|
||||
@ -843,9 +843,11 @@ fn is_inherent_impl_coherent(
|
||||
rustc_has_incoherent_inherent_impls
|
||||
&& !items.items.is_empty()
|
||||
&& items.items.iter().all(|&(_, assoc)| match assoc {
|
||||
AssocItemId::FunctionId(it) => db.function_data(it).rustc_allow_incoherent_impl,
|
||||
AssocItemId::ConstId(it) => db.const_data(it).rustc_allow_incoherent_impl,
|
||||
AssocItemId::TypeAliasId(it) => db.type_alias_data(it).rustc_allow_incoherent_impl,
|
||||
AssocItemId::FunctionId(it) => db.function_data(it).rustc_allow_incoherent_impl(),
|
||||
AssocItemId::ConstId(it) => db.const_data(it).rustc_allow_incoherent_impl(),
|
||||
AssocItemId::TypeAliasId(it) => {
|
||||
db.type_alias_data(it).rustc_allow_incoherent_impl()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -2756,7 +2756,7 @@ impl Evaluator<'_> {
|
||||
return Ok(*o);
|
||||
};
|
||||
let static_data = self.db.static_data(st);
|
||||
let result = if !static_data.is_extern {
|
||||
let result = if !static_data.is_extern() {
|
||||
let konst = self.db.const_eval_static(st).map_err(|e| {
|
||||
MirEvalError::ConstEvalError(static_data.name.as_str().to_owned(), Box::new(e))
|
||||
})?;
|
||||
|
@ -739,7 +739,7 @@ impl HirDisplay for Static {
|
||||
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
|
||||
let data = f.db.static_data(self.id);
|
||||
f.write_str("static ")?;
|
||||
if data.mutable {
|
||||
if data.mutable() {
|
||||
f.write_str("mut ")?;
|
||||
}
|
||||
write!(f, "{}: ", data.name.display(f.db.upcast(), f.edition()))?;
|
||||
|
@ -114,6 +114,7 @@ pub use crate::{
|
||||
pub use {
|
||||
cfg::{CfgAtom, CfgExpr, CfgOptions},
|
||||
hir_def::{
|
||||
Complete,
|
||||
ImportPathConfig,
|
||||
attr::{AttrSourceMap, Attrs, AttrsWithOwner},
|
||||
data::adt::StructKind,
|
||||
@ -254,14 +255,17 @@ impl Crate {
|
||||
self,
|
||||
db: &dyn DefDatabase,
|
||||
query: import_map::Query,
|
||||
) -> impl Iterator<Item = Either<ModuleDef, Macro>> {
|
||||
) -> impl Iterator<Item = (Either<ModuleDef, Macro>, Complete)> {
|
||||
let _p = tracing::info_span!("query_external_importables").entered();
|
||||
import_map::search_dependencies(db, self.into(), &query).into_iter().map(|item| {
|
||||
match ItemInNs::from(item) {
|
||||
ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id),
|
||||
ItemInNs::Macros(mac_id) => Either::Right(mac_id),
|
||||
}
|
||||
})
|
||||
import_map::search_dependencies(db, self.into(), &query).into_iter().map(
|
||||
|(item, do_not_complete)| {
|
||||
let item = match ItemInNs::from(item) {
|
||||
ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id),
|
||||
ItemInNs::Macros(mac_id) => Either::Right(mac_id),
|
||||
};
|
||||
(item, do_not_complete)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn all(db: &dyn HirDatabase) -> Vec<Crate> {
|
||||
@ -811,7 +815,7 @@ impl Module {
|
||||
let items = &db.trait_items(trait_.into()).items;
|
||||
let required_items = items.iter().filter(|&(_, assoc)| match *assoc {
|
||||
AssocItemId::FunctionId(it) => !db.function_data(it).has_body(),
|
||||
AssocItemId::ConstId(id) => !db.const_data(id).has_body,
|
||||
AssocItemId::ConstId(id) => !db.const_data(id).has_body(),
|
||||
AssocItemId::TypeAliasId(it) => db.type_alias_data(it).type_ref.is_none(),
|
||||
});
|
||||
impl_assoc_items_scratch.extend(db.impl_items(impl_def.id).items.iter().cloned());
|
||||
@ -2812,7 +2816,7 @@ impl Static {
|
||||
}
|
||||
|
||||
pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
|
||||
db.static_data(self.id).mutable
|
||||
db.static_data(self.id).mutable()
|
||||
}
|
||||
|
||||
pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
|
||||
@ -2932,6 +2936,11 @@ impl Trait {
|
||||
.map(|it| it.as_ref().clone().into_boxed_slice())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
/// `#[rust_analyzer::completions(...)]` mode.
|
||||
pub fn complete(self, db: &dyn HirDatabase) -> Complete {
|
||||
Complete::extract(true, &self.attrs(db))
|
||||
}
|
||||
}
|
||||
|
||||
impl HasVisibility for Trait {
|
||||
@ -6359,3 +6368,48 @@ where
|
||||
self(item)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_absolute_path<'a, I: Iterator<Item = Symbol> + Clone + 'a>(
|
||||
db: &'a dyn HirDatabase,
|
||||
mut segments: I,
|
||||
) -> impl Iterator<Item = ItemInNs> + use<'a, I> {
|
||||
segments
|
||||
.next()
|
||||
.into_iter()
|
||||
.flat_map(move |crate_name| {
|
||||
db.all_crates()
|
||||
.iter()
|
||||
.filter(|&krate| {
|
||||
krate
|
||||
.extra_data(db)
|
||||
.display_name
|
||||
.as_ref()
|
||||
.is_some_and(|name| *name.crate_name().symbol() == crate_name)
|
||||
})
|
||||
.filter_map(|&krate| {
|
||||
let segments = segments.clone();
|
||||
let mut def_map = db.crate_def_map(krate);
|
||||
let mut module = &def_map[DefMap::ROOT];
|
||||
let mut segments = segments.with_position().peekable();
|
||||
while let Some((_, segment)) = segments.next_if(|&(position, _)| {
|
||||
!matches!(position, itertools::Position::Last | itertools::Position::Only)
|
||||
}) {
|
||||
let res = module
|
||||
.scope
|
||||
.get(&Name::new_symbol_root(segment))
|
||||
.take_types()
|
||||
.and_then(|res| match res {
|
||||
ModuleDefId::ModuleId(it) => Some(it),
|
||||
_ => None,
|
||||
})?;
|
||||
def_map = res.def_map(db.upcast());
|
||||
module = &def_map[res.local_id];
|
||||
}
|
||||
let (_, item_name) = segments.next()?;
|
||||
let res = module.scope.get(&Name::new_symbol_root(item_name));
|
||||
Some(res.iter_items().map(|(item, _)| item.into()))
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.flatten()
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use either::Either;
|
||||
use hir_def::{
|
||||
AdtId, AssocItemId, DefWithBodyId, ExternCrateId, HasModule, ImplId, Lookup, MacroId,
|
||||
AdtId, AssocItemId, Complete, DefWithBodyId, ExternCrateId, HasModule, ImplId, Lookup, MacroId,
|
||||
ModuleDefId, ModuleId, TraitId,
|
||||
db::DefDatabase,
|
||||
item_scope::{ImportId, ImportOrExternCrate, ImportOrGlob},
|
||||
@ -34,6 +34,7 @@ pub struct FileSymbol {
|
||||
/// Whether this symbol is a doc alias for the original symbol.
|
||||
pub is_alias: bool,
|
||||
pub is_assoc: bool,
|
||||
pub do_not_complete: Complete,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
@ -122,35 +123,43 @@ impl<'a> SymbolCollector<'a> {
|
||||
match def {
|
||||
ModuleDefId::ModuleId(id) => this.push_module(id, name),
|
||||
ModuleDefId::FunctionId(id) => {
|
||||
this.push_decl(id, name, false);
|
||||
this.push_decl(id, name, false, None);
|
||||
this.collect_from_body(id, Some(name.clone()));
|
||||
}
|
||||
ModuleDefId::AdtId(AdtId::StructId(id)) => this.push_decl(id, name, false),
|
||||
ModuleDefId::AdtId(AdtId::EnumId(id)) => this.push_decl(id, name, false),
|
||||
ModuleDefId::AdtId(AdtId::UnionId(id)) => this.push_decl(id, name, false),
|
||||
ModuleDefId::AdtId(AdtId::StructId(id)) => {
|
||||
this.push_decl(id, name, false, None);
|
||||
}
|
||||
ModuleDefId::AdtId(AdtId::EnumId(id)) => {
|
||||
this.push_decl(id, name, false, None);
|
||||
}
|
||||
ModuleDefId::AdtId(AdtId::UnionId(id)) => {
|
||||
this.push_decl(id, name, false, None);
|
||||
}
|
||||
ModuleDefId::ConstId(id) => {
|
||||
this.push_decl(id, name, false);
|
||||
this.push_decl(id, name, false, None);
|
||||
this.collect_from_body(id, Some(name.clone()));
|
||||
}
|
||||
ModuleDefId::StaticId(id) => {
|
||||
this.push_decl(id, name, false);
|
||||
this.push_decl(id, name, false, None);
|
||||
this.collect_from_body(id, Some(name.clone()));
|
||||
}
|
||||
ModuleDefId::TraitId(id) => {
|
||||
this.push_decl(id, name, false);
|
||||
this.collect_from_trait(id);
|
||||
let trait_do_not_complete = this.push_decl(id, name, false, None);
|
||||
this.collect_from_trait(id, trait_do_not_complete);
|
||||
}
|
||||
ModuleDefId::TraitAliasId(id) => {
|
||||
this.push_decl(id, name, false);
|
||||
this.push_decl(id, name, false, None);
|
||||
}
|
||||
ModuleDefId::TypeAliasId(id) => {
|
||||
this.push_decl(id, name, false);
|
||||
this.push_decl(id, name, false, None);
|
||||
}
|
||||
ModuleDefId::MacroId(id) => {
|
||||
match id {
|
||||
MacroId::Macro2Id(id) => this.push_decl(id, name, false, None),
|
||||
MacroId::MacroRulesId(id) => this.push_decl(id, name, false, None),
|
||||
MacroId::ProcMacroId(id) => this.push_decl(id, name, false, None),
|
||||
};
|
||||
}
|
||||
ModuleDefId::MacroId(id) => match id {
|
||||
MacroId::Macro2Id(id) => this.push_decl(id, name, false),
|
||||
MacroId::MacroRulesId(id) => this.push_decl(id, name, false),
|
||||
MacroId::ProcMacroId(id) => this.push_decl(id, name, false),
|
||||
},
|
||||
// Don't index these.
|
||||
ModuleDefId::BuiltinType(_) => {}
|
||||
ModuleDefId::EnumVariantId(_) => {}
|
||||
@ -194,6 +203,7 @@ impl<'a> SymbolCollector<'a> {
|
||||
loc: dec_loc,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Complete::Yes,
|
||||
});
|
||||
};
|
||||
|
||||
@ -223,6 +233,7 @@ impl<'a> SymbolCollector<'a> {
|
||||
loc: dec_loc,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Complete::Yes,
|
||||
});
|
||||
};
|
||||
|
||||
@ -281,10 +292,10 @@ impl<'a> SymbolCollector<'a> {
|
||||
for &id in id {
|
||||
if id.module(self.db.upcast()) == module_id {
|
||||
match id {
|
||||
MacroId::Macro2Id(id) => self.push_decl(id, name, false),
|
||||
MacroId::MacroRulesId(id) => self.push_decl(id, name, false),
|
||||
MacroId::ProcMacroId(id) => self.push_decl(id, name, false),
|
||||
}
|
||||
MacroId::Macro2Id(id) => self.push_decl(id, name, false, None),
|
||||
MacroId::MacroRulesId(id) => self.push_decl(id, name, false, None),
|
||||
MacroId::ProcMacroId(id) => self.push_decl(id, name, false, None),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -314,16 +325,16 @@ impl<'a> SymbolCollector<'a> {
|
||||
);
|
||||
self.with_container_name(impl_name, |s| {
|
||||
for &(ref name, assoc_item_id) in &self.db.impl_items(impl_id).items {
|
||||
s.push_assoc_item(assoc_item_id, name)
|
||||
s.push_assoc_item(assoc_item_id, name, None)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn collect_from_trait(&mut self, trait_id: TraitId) {
|
||||
fn collect_from_trait(&mut self, trait_id: TraitId, trait_do_not_complete: Complete) {
|
||||
let trait_data = self.db.trait_data(trait_id);
|
||||
self.with_container_name(Some(trait_data.name.as_str().into()), |s| {
|
||||
for &(ref name, assoc_item_id) in &self.db.trait_items(trait_id).items {
|
||||
s.push_assoc_item(assoc_item_id, name);
|
||||
s.push_assoc_item(assoc_item_id, name, Some(trait_do_not_complete));
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -338,15 +349,26 @@ impl<'a> SymbolCollector<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn push_assoc_item(&mut self, assoc_item_id: AssocItemId, name: &Name) {
|
||||
fn push_assoc_item(
|
||||
&mut self,
|
||||
assoc_item_id: AssocItemId,
|
||||
name: &Name,
|
||||
trait_do_not_complete: Option<Complete>,
|
||||
) {
|
||||
match assoc_item_id {
|
||||
AssocItemId::FunctionId(id) => self.push_decl(id, name, true),
|
||||
AssocItemId::ConstId(id) => self.push_decl(id, name, true),
|
||||
AssocItemId::TypeAliasId(id) => self.push_decl(id, name, true),
|
||||
}
|
||||
AssocItemId::FunctionId(id) => self.push_decl(id, name, true, trait_do_not_complete),
|
||||
AssocItemId::ConstId(id) => self.push_decl(id, name, true, trait_do_not_complete),
|
||||
AssocItemId::TypeAliasId(id) => self.push_decl(id, name, true, trait_do_not_complete),
|
||||
};
|
||||
}
|
||||
|
||||
fn push_decl<L>(&mut self, id: L, name: &Name, is_assoc: bool)
|
||||
fn push_decl<L>(
|
||||
&mut self,
|
||||
id: L,
|
||||
name: &Name,
|
||||
is_assoc: bool,
|
||||
trait_do_not_complete: Option<Complete>,
|
||||
) -> Complete
|
||||
where
|
||||
L: Lookup<Database = dyn DefDatabase> + Into<ModuleDefId>,
|
||||
<L as Lookup>::Data: HasSource,
|
||||
@ -354,7 +376,7 @@ impl<'a> SymbolCollector<'a> {
|
||||
{
|
||||
let loc = id.lookup(self.db.upcast());
|
||||
let source = loc.source(self.db.upcast());
|
||||
let Some(name_node) = source.value.name() else { return };
|
||||
let Some(name_node) = source.value.name() else { return Complete::Yes };
|
||||
let def = ModuleDef::from(id.into());
|
||||
let dec_loc = DeclarationLocation {
|
||||
hir_file_id: source.file_id,
|
||||
@ -362,7 +384,14 @@ impl<'a> SymbolCollector<'a> {
|
||||
name_ptr: AstPtr::new(&name_node).wrap_left(),
|
||||
};
|
||||
|
||||
let mut do_not_complete = Complete::Yes;
|
||||
|
||||
if let Some(attrs) = def.attrs(self.db) {
|
||||
do_not_complete = Complete::extract(matches!(def, ModuleDef::Trait(_)), &attrs);
|
||||
if let Some(trait_do_not_complete) = trait_do_not_complete {
|
||||
do_not_complete = Complete::for_trait_item(trait_do_not_complete, do_not_complete);
|
||||
}
|
||||
|
||||
for alias in attrs.doc_aliases() {
|
||||
self.symbols.insert(FileSymbol {
|
||||
name: alias.clone(),
|
||||
@ -371,6 +400,7 @@ impl<'a> SymbolCollector<'a> {
|
||||
container_name: self.current_container_name.clone(),
|
||||
is_alias: true,
|
||||
is_assoc,
|
||||
do_not_complete,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -382,7 +412,10 @@ impl<'a> SymbolCollector<'a> {
|
||||
loc: dec_loc,
|
||||
is_alias: false,
|
||||
is_assoc,
|
||||
do_not_complete,
|
||||
});
|
||||
|
||||
do_not_complete
|
||||
}
|
||||
|
||||
fn push_module(&mut self, module_id: ModuleId, name: &Name) {
|
||||
@ -399,7 +432,10 @@ impl<'a> SymbolCollector<'a> {
|
||||
|
||||
let def = ModuleDef::Module(module_id.into());
|
||||
|
||||
let mut do_not_complete = Complete::Yes;
|
||||
if let Some(attrs) = def.attrs(self.db) {
|
||||
do_not_complete = Complete::extract(matches!(def, ModuleDef::Trait(_)), &attrs);
|
||||
|
||||
for alias in attrs.doc_aliases() {
|
||||
self.symbols.insert(FileSymbol {
|
||||
name: alias.clone(),
|
||||
@ -408,6 +444,7 @@ impl<'a> SymbolCollector<'a> {
|
||||
container_name: self.current_container_name.clone(),
|
||||
is_alias: true,
|
||||
is_assoc: false,
|
||||
do_not_complete,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -419,6 +456,7 @@ impl<'a> SymbolCollector<'a> {
|
||||
loc: dec_loc,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ pub(crate) fn replace_derive_with_manual_impl(
|
||||
NameToImport::exact_case_sensitive(path.segments().last()?.to_string()),
|
||||
items_locator::AssocSearchMode::Exclude,
|
||||
)
|
||||
.filter_map(|item| match item.into_module_def() {
|
||||
.filter_map(|(item, _)| match item.into_module_def() {
|
||||
ModuleDef::Trait(trait_) => Some(trait_),
|
||||
_ => None,
|
||||
})
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use hir::{HasContainer, ItemContainer, MethodCandidateCallback, Name};
|
||||
use hir::{Complete, HasContainer, ItemContainer, MethodCandidateCallback, Name};
|
||||
use ide_db::FxHashSet;
|
||||
use syntax::SmolStr;
|
||||
|
||||
@ -259,7 +259,9 @@ fn complete_methods(
|
||||
// This needs to come before the `seen_methods` test, so that if we see the same method twice,
|
||||
// once as inherent and once not, we will include it.
|
||||
if let ItemContainer::Trait(trait_) = func.container(self.ctx.db) {
|
||||
if self.ctx.exclude_traits.contains(&trait_) {
|
||||
if self.ctx.exclude_traits.contains(&trait_)
|
||||
|| trait_.complete(self.ctx.db) == Complete::IgnoreMethods
|
||||
{
|
||||
return ControlFlow::Continue(());
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use hir::{Name, PathCandidateCallback, ScopeDef, sym};
|
||||
use hir::{Complete, Name, PathCandidateCallback, ScopeDef, sym};
|
||||
use ide_db::FxHashSet;
|
||||
use syntax::ast;
|
||||
|
||||
@ -33,10 +33,10 @@ where
|
||||
fn on_trait_item(&mut self, item: hir::AssocItem) -> ControlFlow<()> {
|
||||
// The excluded check needs to come before the `seen` test, so that if we see the same method twice,
|
||||
// once as inherent and once not, we will include it.
|
||||
if item
|
||||
.container_trait(self.ctx.db)
|
||||
.is_none_or(|trait_| !self.ctx.exclude_traits.contains(&trait_))
|
||||
&& self.seen.insert(item)
|
||||
if item.container_trait(self.ctx.db).is_none_or(|trait_| {
|
||||
!self.ctx.exclude_traits.contains(&trait_)
|
||||
&& trait_.complete(self.ctx.db) != Complete::IgnoreMethods
|
||||
}) && self.seen.insert(item)
|
||||
{
|
||||
(self.add_assoc_item)(self.acc, item);
|
||||
}
|
||||
@ -104,7 +104,9 @@ pub(crate) fn complete_expr_path(
|
||||
.iter()
|
||||
.copied()
|
||||
.map(hir::Trait::from)
|
||||
.filter(|it| !ctx.exclude_traits.contains(it))
|
||||
.filter(|it| {
|
||||
!ctx.exclude_traits.contains(it) && it.complete(ctx.db) != Complete::IgnoreMethods
|
||||
})
|
||||
.flat_map(|it| it.items(ctx.sema.db))
|
||||
.for_each(|item| add_assoc_item(acc, item)),
|
||||
Qualified::TypeAnchor { trait_: Some(trait_), .. } => {
|
||||
|
@ -268,19 +268,7 @@ fn import_on_the_fly(
|
||||
&& !ctx.is_item_hidden(original_item)
|
||||
&& ctx.check_stability(original_item.attrs(ctx.db).as_deref())
|
||||
})
|
||||
.filter(|import| {
|
||||
let def = import.item_to_import.into_module_def();
|
||||
if let Some(&kind) = ctx.exclude_flyimport.get(&def) {
|
||||
if kind == AutoImportExclusionType::Always {
|
||||
return false;
|
||||
}
|
||||
let method_imported = import.item_to_import != import.original_item;
|
||||
if method_imported {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
})
|
||||
.filter(|import| filter_excluded_flyimport(ctx, import))
|
||||
.sorted_by(|a, b| {
|
||||
let key = |import_path| {
|
||||
(
|
||||
@ -366,24 +354,7 @@ fn import_on_the_fly_method(
|
||||
!ctx.is_item_hidden(&import.item_to_import)
|
||||
&& !ctx.is_item_hidden(&import.original_item)
|
||||
})
|
||||
.filter(|import| {
|
||||
let def = import.item_to_import.into_module_def();
|
||||
if let Some(&kind) = ctx.exclude_flyimport.get(&def) {
|
||||
if kind == AutoImportExclusionType::Always {
|
||||
return false;
|
||||
}
|
||||
let method_imported = import.item_to_import != import.original_item;
|
||||
if method_imported {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if let ModuleDef::Trait(_) = import.item_to_import.into_module_def() {
|
||||
!ctx.exclude_flyimport.contains_key(&def)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
})
|
||||
.filter(|import| filter_excluded_flyimport(ctx, import))
|
||||
.sorted_by(|a, b| {
|
||||
let key = |import_path| {
|
||||
(
|
||||
@ -401,6 +372,28 @@ fn import_on_the_fly_method(
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn filter_excluded_flyimport(ctx: &CompletionContext<'_>, import: &LocatedImport) -> bool {
|
||||
let def = import.item_to_import.into_module_def();
|
||||
let is_exclude_flyimport = ctx.exclude_flyimport.get(&def).copied();
|
||||
|
||||
if matches!(is_exclude_flyimport, Some(AutoImportExclusionType::Always))
|
||||
|| !import.complete_in_flyimport.0
|
||||
{
|
||||
return false;
|
||||
}
|
||||
let method_imported = import.item_to_import != import.original_item;
|
||||
if method_imported
|
||||
&& (is_exclude_flyimport.is_some()
|
||||
|| ctx.exclude_flyimport.contains_key(&import.original_item.into_module_def()))
|
||||
{
|
||||
// If this is a method, exclude it either if it was excluded itself (which may not be caught above,
|
||||
// because `item_to_import` is the trait), or if its trait was excluded. We don't need to check
|
||||
// the attributes here, since they pass from trait to methods on import map construction.
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn import_name(ctx: &CompletionContext<'_>) -> String {
|
||||
let token_kind = ctx.token.kind();
|
||||
|
||||
|
@ -8,8 +8,8 @@ use std::{iter, ops::ControlFlow};
|
||||
|
||||
use base_db::{RootQueryDb as _, salsa::AsDynDatabase};
|
||||
use hir::{
|
||||
DisplayTarget, HasAttrs, Local, ModPath, ModuleDef, ModuleSource, Name, PathResolution,
|
||||
ScopeDef, Semantics, SemanticsScope, Symbol, Type, TypeInfo,
|
||||
DisplayTarget, HasAttrs, Local, ModuleDef, ModuleSource, Name, PathResolution, ScopeDef,
|
||||
Semantics, SemanticsScope, Symbol, Type, TypeInfo,
|
||||
};
|
||||
use ide_db::{
|
||||
FilePosition, FxHashMap, FxHashSet, RootDatabase, famous_defs::FamousDefs,
|
||||
@ -796,15 +796,12 @@ impl<'a> CompletionContext<'a> {
|
||||
.exclude_traits
|
||||
.iter()
|
||||
.filter_map(|path| {
|
||||
scope
|
||||
.resolve_mod_path(&ModPath::from_segments(
|
||||
hir::PathKind::Plain,
|
||||
path.split("::").map(Symbol::intern).map(Name::new_symbol_root),
|
||||
))
|
||||
.find_map(|it| match it {
|
||||
hir::resolve_absolute_path(db, path.split("::").map(Symbol::intern)).find_map(
|
||||
|it| match it {
|
||||
hir::ItemInNs::Types(ModuleDef::Trait(t)) => Some(t),
|
||||
_ => None,
|
||||
})
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
@ -812,11 +809,7 @@ impl<'a> CompletionContext<'a> {
|
||||
.exclude_flyimport
|
||||
.iter()
|
||||
.flat_map(|(path, kind)| {
|
||||
scope
|
||||
.resolve_mod_path(&ModPath::from_segments(
|
||||
hir::PathKind::Plain,
|
||||
path.split("::").map(Symbol::intern).map(Name::new_symbol_root),
|
||||
))
|
||||
hir::resolve_absolute_path(db, path.split("::").map(Symbol::intern))
|
||||
.map(|it| (it.into_module_def(), *kind))
|
||||
})
|
||||
.collect();
|
||||
|
@ -334,7 +334,7 @@ pub(crate) fn render_expr(
|
||||
continue;
|
||||
};
|
||||
|
||||
item.add_import(LocatedImport::new(path, trait_item, trait_item));
|
||||
item.add_import(LocatedImport::new_no_completion(path, trait_item, trait_item));
|
||||
}
|
||||
|
||||
Some(item)
|
||||
|
@ -174,7 +174,7 @@ fn import_edits(ctx: &CompletionContext<'_>, requires: &[ModPath]) -> Option<Vec
|
||||
ctx.config.insert_use.prefix_kind,
|
||||
import_cfg,
|
||||
)?;
|
||||
Some((path.len() > 1).then(|| LocatedImport::new(path.clone(), item, item)))
|
||||
Some((path.len() > 1).then(|| LocatedImport::new_no_completion(path.clone(), item, item)))
|
||||
};
|
||||
let mut res = Vec::with_capacity(requires.len());
|
||||
for import in requires {
|
||||
|
@ -1555,7 +1555,10 @@ fn main() {
|
||||
#[test]
|
||||
fn excluded_trait_method_is_excluded() {
|
||||
check_with_config(
|
||||
CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
|
||||
CompletionConfig {
|
||||
exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()],
|
||||
..TEST_CONFIG
|
||||
},
|
||||
r#"
|
||||
trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
@ -1575,23 +1578,20 @@ fn foo() {
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
me bar() (as ExcludedTrait) fn(&self)
|
||||
me baz() (as ExcludedTrait) fn(&self)
|
||||
me foo() (as ExcludedTrait) fn(&self)
|
||||
me inherent() fn(&self)
|
||||
sn box Box::new(expr)
|
||||
sn call function(expr)
|
||||
sn const const {}
|
||||
sn dbg dbg!(expr)
|
||||
sn dbgr dbg!(&expr)
|
||||
sn deref *expr
|
||||
sn let let
|
||||
sn letm let mut
|
||||
sn match match expr {}
|
||||
sn ref &expr
|
||||
sn refm &mut expr
|
||||
sn return return expr
|
||||
sn unsafe unsafe {}
|
||||
me inherent() fn(&self)
|
||||
sn box Box::new(expr)
|
||||
sn call function(expr)
|
||||
sn const const {}
|
||||
sn dbg dbg!(expr)
|
||||
sn dbgr dbg!(&expr)
|
||||
sn deref *expr
|
||||
sn let let
|
||||
sn letm let mut
|
||||
sn match match expr {}
|
||||
sn ref &expr
|
||||
sn refm &mut expr
|
||||
sn return return expr
|
||||
sn unsafe unsafe {}
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
@ -1599,7 +1599,10 @@ fn foo() {
|
||||
#[test]
|
||||
fn excluded_trait_not_excluded_when_inherent() {
|
||||
check_with_config(
|
||||
CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
|
||||
CompletionConfig {
|
||||
exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()],
|
||||
..TEST_CONFIG
|
||||
},
|
||||
r#"
|
||||
trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
@ -1633,7 +1636,10 @@ fn foo(v: &dyn ExcludedTrait) {
|
||||
"#]],
|
||||
);
|
||||
check_with_config(
|
||||
CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
|
||||
CompletionConfig {
|
||||
exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()],
|
||||
..TEST_CONFIG
|
||||
},
|
||||
r#"
|
||||
trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
@ -1667,7 +1673,10 @@ fn foo(v: impl ExcludedTrait) {
|
||||
"#]],
|
||||
);
|
||||
check_with_config(
|
||||
CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
|
||||
CompletionConfig {
|
||||
exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()],
|
||||
..TEST_CONFIG
|
||||
},
|
||||
r#"
|
||||
trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
@ -1706,7 +1715,7 @@ fn foo<T: ExcludedTrait>(v: T) {
|
||||
fn excluded_trait_method_is_excluded_from_flyimport() {
|
||||
check_with_config(
|
||||
CompletionConfig {
|
||||
exclude_traits: &["test::module2::ExcludedTrait".to_owned()],
|
||||
exclude_traits: &["ra_test_fixture::module2::ExcludedTrait".to_owned()],
|
||||
..TEST_CONFIG
|
||||
},
|
||||
r#"
|
||||
@ -1730,23 +1739,20 @@ fn foo() {
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
me bar() (use module2::ExcludedTrait) fn(&self)
|
||||
me baz() (use module2::ExcludedTrait) fn(&self)
|
||||
me foo() (use module2::ExcludedTrait) fn(&self)
|
||||
me inherent() fn(&self)
|
||||
sn box Box::new(expr)
|
||||
sn call function(expr)
|
||||
sn const const {}
|
||||
sn dbg dbg!(expr)
|
||||
sn dbgr dbg!(&expr)
|
||||
sn deref *expr
|
||||
sn let let
|
||||
sn letm let mut
|
||||
sn match match expr {}
|
||||
sn ref &expr
|
||||
sn refm &mut expr
|
||||
sn return return expr
|
||||
sn unsafe unsafe {}
|
||||
me inherent() fn(&self)
|
||||
sn box Box::new(expr)
|
||||
sn call function(expr)
|
||||
sn const const {}
|
||||
sn dbg dbg!(expr)
|
||||
sn dbgr dbg!(&expr)
|
||||
sn deref *expr
|
||||
sn let let
|
||||
sn letm let mut
|
||||
sn match match expr {}
|
||||
sn ref &expr
|
||||
sn refm &mut expr
|
||||
sn return return expr
|
||||
sn unsafe unsafe {}
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
@ -1756,7 +1762,7 @@ fn flyimport_excluded_trait_method_is_excluded_from_flyimport() {
|
||||
check_with_config(
|
||||
CompletionConfig {
|
||||
exclude_flyimport: vec![(
|
||||
"test::module2::ExcludedTrait".to_owned(),
|
||||
"ra_test_fixture::module2::ExcludedTrait".to_owned(),
|
||||
AutoImportExclusionType::Methods,
|
||||
)],
|
||||
..TEST_CONFIG
|
||||
@ -1782,23 +1788,20 @@ fn foo() {
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
me bar() (use module2::ExcludedTrait) fn(&self)
|
||||
me baz() (use module2::ExcludedTrait) fn(&self)
|
||||
me foo() (use module2::ExcludedTrait) fn(&self)
|
||||
me inherent() fn(&self)
|
||||
sn box Box::new(expr)
|
||||
sn call function(expr)
|
||||
sn const const {}
|
||||
sn dbg dbg!(expr)
|
||||
sn dbgr dbg!(&expr)
|
||||
sn deref *expr
|
||||
sn let let
|
||||
sn letm let mut
|
||||
sn match match expr {}
|
||||
sn ref &expr
|
||||
sn refm &mut expr
|
||||
sn return return expr
|
||||
sn unsafe unsafe {}
|
||||
me inherent() fn(&self)
|
||||
sn box Box::new(expr)
|
||||
sn call function(expr)
|
||||
sn const const {}
|
||||
sn dbg dbg!(expr)
|
||||
sn dbgr dbg!(&expr)
|
||||
sn deref *expr
|
||||
sn let let
|
||||
sn letm let mut
|
||||
sn match match expr {}
|
||||
sn ref &expr
|
||||
sn refm &mut expr
|
||||
sn return return expr
|
||||
sn unsafe unsafe {}
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
@ -1806,7 +1809,10 @@ fn foo() {
|
||||
#[test]
|
||||
fn excluded_trait_method_is_excluded_from_path_completion() {
|
||||
check_with_config(
|
||||
CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
|
||||
CompletionConfig {
|
||||
exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()],
|
||||
..TEST_CONFIG
|
||||
},
|
||||
r#"
|
||||
pub trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
@ -1826,10 +1832,7 @@ fn foo() {
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
me bar(…) (as ExcludedTrait) fn(&self)
|
||||
me baz(…) (as ExcludedTrait) fn(&self)
|
||||
me foo(…) (as ExcludedTrait) fn(&self)
|
||||
me inherent(…) fn(&self)
|
||||
me inherent(…) fn(&self)
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
@ -1837,7 +1840,10 @@ fn foo() {
|
||||
#[test]
|
||||
fn excluded_trait_method_is_not_excluded_when_trait_is_specified() {
|
||||
check_with_config(
|
||||
CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
|
||||
CompletionConfig {
|
||||
exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()],
|
||||
..TEST_CONFIG
|
||||
},
|
||||
r#"
|
||||
pub trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
@ -1863,7 +1869,10 @@ fn foo() {
|
||||
"#]],
|
||||
);
|
||||
check_with_config(
|
||||
CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
|
||||
CompletionConfig {
|
||||
exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()],
|
||||
..TEST_CONFIG
|
||||
},
|
||||
r#"
|
||||
pub trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
@ -1893,7 +1902,10 @@ fn foo() {
|
||||
#[test]
|
||||
fn excluded_trait_not_excluded_when_inherent_path() {
|
||||
check_with_config(
|
||||
CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
|
||||
CompletionConfig {
|
||||
exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()],
|
||||
..TEST_CONFIG
|
||||
},
|
||||
r#"
|
||||
trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
@ -1914,7 +1926,10 @@ fn foo() {
|
||||
"#]],
|
||||
);
|
||||
check_with_config(
|
||||
CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
|
||||
CompletionConfig {
|
||||
exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()],
|
||||
..TEST_CONFIG
|
||||
},
|
||||
r#"
|
||||
trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
|
@ -1810,9 +1810,10 @@ fn function() {
|
||||
|
||||
#[test]
|
||||
fn excluded_trait_item_included_when_exact_match() {
|
||||
// FIXME: This does not work, we need to change the code.
|
||||
check_with_config(
|
||||
CompletionConfig {
|
||||
exclude_traits: &["test::module2::ExcludedTrait".to_owned()],
|
||||
exclude_traits: &["ra_test_fixture::module2::ExcludedTrait".to_owned()],
|
||||
..TEST_CONFIG
|
||||
},
|
||||
r#"
|
||||
@ -1830,8 +1831,120 @@ fn foo() {
|
||||
true.foo$0
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
me foo() (use module2::ExcludedTrait) fn(&self)
|
||||
"#]],
|
||||
expect![""],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn excluded_via_attr() {
|
||||
check(
|
||||
r#"
|
||||
mod module2 {
|
||||
#[rust_analyzer::completions(ignore_flyimport)]
|
||||
pub trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
fn bar(&self) {}
|
||||
fn baz(&self) {}
|
||||
}
|
||||
|
||||
impl<T> ExcludedTrait for T {}
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
true.$0
|
||||
}
|
||||
"#,
|
||||
expect![""],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
mod module2 {
|
||||
#[rust_analyzer::completions(ignore_flyimport_methods)]
|
||||
pub trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
fn bar(&self) {}
|
||||
fn baz(&self) {}
|
||||
}
|
||||
|
||||
impl<T> ExcludedTrait for T {}
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
true.$0
|
||||
}
|
||||
"#,
|
||||
expect![""],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
mod module2 {
|
||||
#[rust_analyzer::completions(ignore_methods)]
|
||||
pub trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
fn bar(&self) {}
|
||||
fn baz(&self) {}
|
||||
}
|
||||
|
||||
impl<T> ExcludedTrait for T {}
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
true.$0
|
||||
}
|
||||
"#,
|
||||
expect![""],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
mod module2 {
|
||||
#[rust_analyzer::completions(ignore_flyimport)]
|
||||
pub trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
fn bar(&self) {}
|
||||
fn baz(&self) {}
|
||||
}
|
||||
|
||||
impl<T> ExcludedTrait for T {}
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
ExcludedTrait$0
|
||||
}
|
||||
"#,
|
||||
expect![""],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
mod module2 {
|
||||
#[rust_analyzer::completions(ignore_methods)]
|
||||
pub trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
fn bar(&self) {}
|
||||
fn baz(&self) {}
|
||||
}
|
||||
|
||||
impl<T> ExcludedTrait for T {}
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
ExcludedTrait$0
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
tt ExcludedTrait (use module2::ExcludedTrait)
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
mod module2 {
|
||||
#[rust_analyzer::completions(ignore_flyimport)]
|
||||
pub struct Foo {}
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
Foo$0
|
||||
}
|
||||
"#,
|
||||
expect![""],
|
||||
);
|
||||
}
|
||||
|
@ -3,8 +3,8 @@
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use hir::{
|
||||
AsAssocItem, AssocItem, AssocItemContainer, Crate, HasCrate, ImportPathConfig, ItemInNs,
|
||||
ModPath, Module, ModuleDef, Name, PathResolution, PrefixKind, ScopeDef, Semantics,
|
||||
AsAssocItem, AssocItem, AssocItemContainer, Complete, Crate, HasCrate, ImportPathConfig,
|
||||
ItemInNs, ModPath, Module, ModuleDef, Name, PathResolution, PrefixKind, ScopeDef, Semantics,
|
||||
SemanticsScope, Trait, TyFingerprint, Type, db::HirDatabase,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
@ -183,6 +183,9 @@ impl ImportAssets {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct CompleteInFlyimport(pub bool);
|
||||
|
||||
/// An import (not necessary the only one) that corresponds a certain given [`PathImportCandidate`].
|
||||
/// (the structure is not entirely correct, since there can be situations requiring two imports, see FIXME below for the details)
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
@ -198,11 +201,31 @@ pub struct LocatedImport {
|
||||
/// the original item is the associated constant, but the import has to be a trait that
|
||||
/// defines this constant.
|
||||
pub original_item: ItemInNs,
|
||||
/// The value of `#[rust_analyzer::completions(...)]`, if existing.
|
||||
pub complete_in_flyimport: CompleteInFlyimport,
|
||||
}
|
||||
|
||||
impl LocatedImport {
|
||||
pub fn new(import_path: ModPath, item_to_import: ItemInNs, original_item: ItemInNs) -> Self {
|
||||
Self { import_path, item_to_import, original_item }
|
||||
pub fn new(
|
||||
import_path: ModPath,
|
||||
item_to_import: ItemInNs,
|
||||
original_item: ItemInNs,
|
||||
complete_in_flyimport: CompleteInFlyimport,
|
||||
) -> Self {
|
||||
Self { import_path, item_to_import, original_item, complete_in_flyimport }
|
||||
}
|
||||
|
||||
pub fn new_no_completion(
|
||||
import_path: ModPath,
|
||||
item_to_import: ItemInNs,
|
||||
original_item: ItemInNs,
|
||||
) -> Self {
|
||||
Self {
|
||||
import_path,
|
||||
item_to_import,
|
||||
original_item,
|
||||
complete_in_flyimport: CompleteInFlyimport(true),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -351,12 +374,17 @@ fn path_applicable_imports(
|
||||
// see also an ignored test under FIXME comment in the qualify_path.rs module
|
||||
AssocSearchMode::Exclude,
|
||||
)
|
||||
.filter_map(|item| {
|
||||
.filter_map(|(item, do_not_complete)| {
|
||||
if !scope_filter(item) {
|
||||
return None;
|
||||
}
|
||||
let mod_path = mod_path(item)?;
|
||||
Some(LocatedImport::new(mod_path, item, item))
|
||||
Some(LocatedImport::new(
|
||||
mod_path,
|
||||
item,
|
||||
item,
|
||||
CompleteInFlyimport(do_not_complete != Complete::IgnoreFlyimport),
|
||||
))
|
||||
})
|
||||
.take(DEFAULT_QUERY_SEARCH_LIMIT)
|
||||
.collect()
|
||||
@ -371,7 +399,7 @@ fn path_applicable_imports(
|
||||
NameToImport::Exact(first_qsegment.as_str().to_owned(), true),
|
||||
AssocSearchMode::Exclude,
|
||||
)
|
||||
.filter_map(|item| {
|
||||
.filter_map(|(item, do_not_complete)| {
|
||||
// we found imports for `first_qsegment`, now we need to filter these imports by whether
|
||||
// they result in resolving the rest of the path successfully
|
||||
validate_resolvable(
|
||||
@ -382,6 +410,7 @@ fn path_applicable_imports(
|
||||
&path_candidate.name,
|
||||
item,
|
||||
qualifier_rest,
|
||||
CompleteInFlyimport(do_not_complete != Complete::IgnoreFlyimport),
|
||||
)
|
||||
})
|
||||
.take(DEFAULT_QUERY_SEARCH_LIMIT)
|
||||
@ -399,6 +428,7 @@ fn validate_resolvable(
|
||||
candidate: &NameToImport,
|
||||
resolved_qualifier: ItemInNs,
|
||||
unresolved_qualifier: &[Name],
|
||||
complete_in_flyimport: CompleteInFlyimport,
|
||||
) -> Option<LocatedImport> {
|
||||
let _p = tracing::info_span!("ImportAssets::import_for_item").entered();
|
||||
|
||||
@ -434,7 +464,14 @@ fn validate_resolvable(
|
||||
false => ControlFlow::Continue(()),
|
||||
},
|
||||
)
|
||||
.map(|item| LocatedImport::new(import_path_candidate, resolved_qualifier, item));
|
||||
.map(|item| {
|
||||
LocatedImport::new(
|
||||
import_path_candidate,
|
||||
resolved_qualifier,
|
||||
item,
|
||||
complete_in_flyimport,
|
||||
)
|
||||
});
|
||||
}
|
||||
// FIXME
|
||||
ModuleDef::Trait(_) => return None,
|
||||
@ -472,6 +509,7 @@ fn validate_resolvable(
|
||||
import_path_candidate.clone(),
|
||||
resolved_qualifier,
|
||||
assoc_to_item(assoc),
|
||||
complete_in_flyimport,
|
||||
))
|
||||
})
|
||||
}
|
||||
@ -510,15 +548,15 @@ fn trait_applicable_items(
|
||||
let env_traits = trait_candidate.receiver_ty.env_traits(db);
|
||||
let related_traits = inherent_traits.chain(env_traits).collect::<FxHashSet<_>>();
|
||||
|
||||
let mut required_assoc_items = FxHashSet::default();
|
||||
let mut required_assoc_items = FxHashMap::default();
|
||||
let mut trait_candidates: FxHashSet<_> = items_locator::items_with_name(
|
||||
db,
|
||||
current_crate,
|
||||
trait_candidate.assoc_item_name.clone(),
|
||||
AssocSearchMode::AssocItemsOnly,
|
||||
)
|
||||
.filter_map(|input| item_as_assoc(db, input))
|
||||
.filter_map(|assoc| {
|
||||
.filter_map(|(input, do_not_complete)| Some((item_as_assoc(db, input)?, do_not_complete)))
|
||||
.filter_map(|(assoc, do_not_complete)| {
|
||||
if !trait_assoc_item && matches!(assoc, AssocItem::Const(_) | AssocItem::TypeAlias(_)) {
|
||||
return None;
|
||||
}
|
||||
@ -527,7 +565,8 @@ fn trait_applicable_items(
|
||||
if related_traits.contains(&assoc_item_trait) {
|
||||
return None;
|
||||
}
|
||||
required_assoc_items.insert(assoc);
|
||||
required_assoc_items
|
||||
.insert(assoc, CompleteInFlyimport(do_not_complete != Complete::IgnoreFlyimport));
|
||||
Some(assoc_item_trait.into())
|
||||
})
|
||||
.collect();
|
||||
@ -599,7 +638,7 @@ fn trait_applicable_items(
|
||||
None,
|
||||
None,
|
||||
|assoc| {
|
||||
if required_assoc_items.contains(&assoc) {
|
||||
if let Some(&complete_in_flyimport) = required_assoc_items.get(&assoc) {
|
||||
let located_trait = assoc.container_trait(db).filter(|&it| scope_filter(it))?;
|
||||
let trait_item = ItemInNs::from(ModuleDef::from(located_trait));
|
||||
let import_path = trait_import_paths
|
||||
@ -610,6 +649,7 @@ fn trait_applicable_items(
|
||||
import_path,
|
||||
trait_item,
|
||||
assoc_to_item(assoc),
|
||||
complete_in_flyimport,
|
||||
));
|
||||
}
|
||||
None::<()>
|
||||
@ -624,7 +664,7 @@ fn trait_applicable_items(
|
||||
None,
|
||||
|function| {
|
||||
let assoc = function.as_assoc_item(db)?;
|
||||
if required_assoc_items.contains(&assoc) {
|
||||
if let Some(&complete_in_flyimport) = required_assoc_items.get(&assoc) {
|
||||
let located_trait = assoc.container_trait(db).filter(|&it| scope_filter(it))?;
|
||||
let trait_item = ItemInNs::from(ModuleDef::from(located_trait));
|
||||
let import_path = trait_import_paths
|
||||
@ -635,6 +675,7 @@ fn trait_applicable_items(
|
||||
import_path,
|
||||
trait_item,
|
||||
assoc_to_item(assoc),
|
||||
complete_in_flyimport,
|
||||
));
|
||||
}
|
||||
None::<()>
|
||||
|
@ -5,7 +5,7 @@
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use either::Either;
|
||||
use hir::{Crate, ItemInNs, Module, import_map};
|
||||
use hir::{Complete, Crate, ItemInNs, Module, import_map};
|
||||
|
||||
use crate::{
|
||||
RootDatabase,
|
||||
@ -25,7 +25,7 @@ pub fn items_with_name(
|
||||
krate: Crate,
|
||||
name: NameToImport,
|
||||
assoc_item_search: AssocSearchMode,
|
||||
) -> impl Iterator<Item = ItemInNs> {
|
||||
) -> impl Iterator<Item = (ItemInNs, Complete)> {
|
||||
let _p = tracing::info_span!("items_with_name", name = name.text(), assoc_item_search = ?assoc_item_search, crate = ?krate.display_name(db).map(|name| name.to_string()))
|
||||
.entered();
|
||||
|
||||
@ -123,26 +123,29 @@ fn find_items(
|
||||
krate: Crate,
|
||||
local_query: symbol_index::Query,
|
||||
external_query: import_map::Query,
|
||||
) -> impl Iterator<Item = ItemInNs> {
|
||||
) -> impl Iterator<Item = (ItemInNs, Complete)> {
|
||||
let _p = tracing::info_span!("find_items").entered();
|
||||
|
||||
// NOTE: `external_query` includes `assoc_item_search`, so we don't need to
|
||||
// filter on our own.
|
||||
let external_importables =
|
||||
krate.query_external_importables(db, external_query).map(|external_importable| {
|
||||
match external_importable {
|
||||
let external_importables = krate.query_external_importables(db, external_query).map(
|
||||
|(external_importable, do_not_complete)| {
|
||||
let external_importable = match external_importable {
|
||||
Either::Left(module_def) => ItemInNs::from(module_def),
|
||||
Either::Right(macro_def) => ItemInNs::from(macro_def),
|
||||
}
|
||||
});
|
||||
};
|
||||
(external_importable, do_not_complete)
|
||||
},
|
||||
);
|
||||
|
||||
// Query the local crate using the symbol index.
|
||||
let mut local_results = Vec::new();
|
||||
local_query.search(&symbol_index::crate_symbols(db, krate), |local_candidate| {
|
||||
local_results.push(match local_candidate.def {
|
||||
let def = match local_candidate.def {
|
||||
hir::ModuleDef::Macro(macro_def) => ItemInNs::Macros(macro_def),
|
||||
def => ItemInNs::from(def),
|
||||
});
|
||||
};
|
||||
local_results.push((def, local_candidate.do_not_complete));
|
||||
ControlFlow::<()>::Continue(())
|
||||
});
|
||||
local_results.into_iter().chain(external_importables)
|
||||
|
@ -42,6 +42,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "Struct",
|
||||
@ -75,6 +76,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "mul1",
|
||||
@ -108,6 +110,7 @@
|
||||
container_name: None,
|
||||
is_alias: true,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "mul2",
|
||||
@ -141,6 +144,7 @@
|
||||
container_name: None,
|
||||
is_alias: true,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "s1",
|
||||
@ -174,6 +178,7 @@
|
||||
container_name: None,
|
||||
is_alias: true,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "s1",
|
||||
@ -207,6 +212,7 @@
|
||||
container_name: None,
|
||||
is_alias: true,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "s2",
|
||||
@ -240,6 +246,7 @@
|
||||
container_name: None,
|
||||
is_alias: true,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
],
|
||||
),
|
||||
|
@ -40,6 +40,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "CONST",
|
||||
@ -71,6 +72,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "CONST_WITH_INNER",
|
||||
@ -102,6 +104,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "Enum",
|
||||
@ -135,6 +138,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "ItemLikeMacro",
|
||||
@ -168,6 +172,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "Macro",
|
||||
@ -201,6 +206,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "STATIC",
|
||||
@ -232,6 +238,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "Struct",
|
||||
@ -265,6 +272,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "StructFromMacro",
|
||||
@ -295,6 +303,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "StructInFn",
|
||||
@ -330,6 +339,7 @@
|
||||
),
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "StructInNamedConst",
|
||||
@ -365,6 +375,7 @@
|
||||
),
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "StructInUnnamedConst",
|
||||
@ -398,6 +409,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "StructT",
|
||||
@ -431,6 +443,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "Trait",
|
||||
@ -462,6 +475,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "Trait",
|
||||
@ -495,6 +509,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "Union",
|
||||
@ -528,6 +543,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "a_mod",
|
||||
@ -563,6 +579,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "b_mod",
|
||||
@ -598,6 +615,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "define_struct",
|
||||
@ -631,6 +649,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "generic_impl_fn",
|
||||
@ -664,6 +683,7 @@
|
||||
),
|
||||
is_alias: false,
|
||||
is_assoc: true,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "impl_fn",
|
||||
@ -697,6 +717,7 @@
|
||||
),
|
||||
is_alias: false,
|
||||
is_assoc: true,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "macro_rules_macro",
|
||||
@ -730,6 +751,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "main",
|
||||
@ -761,6 +783,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "really_define_struct",
|
||||
@ -794,6 +817,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "trait_fn",
|
||||
@ -827,6 +851,7 @@
|
||||
),
|
||||
is_alias: false,
|
||||
is_assoc: true,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
],
|
||||
),
|
||||
@ -873,6 +898,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
],
|
||||
),
|
||||
@ -917,6 +943,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "IsThisJustATrait",
|
||||
@ -950,6 +977,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "StructInModB",
|
||||
@ -983,6 +1011,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "SuperItemLikeMacro",
|
||||
@ -1016,6 +1045,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "ThisStruct",
|
||||
@ -1049,6 +1079,7 @@
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
is_assoc: false,
|
||||
do_not_complete: Yes,
|
||||
},
|
||||
],
|
||||
),
|
||||
|
@ -521,4 +521,8 @@ define_symbols! {
|
||||
win64,
|
||||
array,
|
||||
boxed_slice,
|
||||
completions,
|
||||
ignore_flyimport,
|
||||
ignore_flyimport_methods,
|
||||
ignore_methods,
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user