mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-11-02 04:48:13 +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
30 changed files with 770 additions and 293 deletions
|
|
@ -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,
|
||||
},
|
||||
],
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue