Merge commit '37f84c101b' into sync-from-ra

This commit is contained in:
Laurențiu Nicola 2023-07-17 16:49:15 +03:00
parent 6502421771
commit 4704881b64
311 changed files with 13700 additions and 9110 deletions

View file

@ -21,7 +21,7 @@ once_cell = "1.17.0"
either = "1.7.0"
itertools = "0.10.5"
arrayvec = "0.7.2"
indexmap = "1.9.1"
indexmap = "2.0.0"
memchr = "2.5.0"
triomphe.workspace = true
nohash-hasher.workspace = true

View file

@ -99,8 +99,8 @@ impl RootDatabase {
hir::db::AstIdMapQuery
hir::db::ParseMacroExpansionQuery
hir::db::InternMacroCallQuery
hir::db::MacroArgTextQuery
hir::db::MacroDefQuery
hir::db::MacroArgNodeQuery
hir::db::DeclMacroExpanderQuery
hir::db::MacroExpandQuery
hir::db::ExpandProcMacroQuery
hir::db::HygieneFrameQuery

View file

@ -9,7 +9,10 @@ use syntax::{
AstToken, SyntaxKind, SyntaxToken, TokenAtOffset,
};
use crate::{defs::Definition, generated, RootDatabase};
use crate::{
defs::{Definition, IdentClass},
generated, RootDatabase,
};
pub fn item_name(db: &RootDatabase, item: ItemInNs) -> Option<Name> {
match item {
@ -109,3 +112,16 @@ pub fn is_editable_crate(krate: Crate, db: &RootDatabase) -> bool {
let source_root_id = db.file_source_root(root_file);
!db.source_root(source_root_id).is_library
}
pub fn get_definition(
sema: &Semantics<'_, RootDatabase>,
token: SyntaxToken,
) -> Option<Definition> {
for token in sema.descend_into_macros(token) {
let def = IdentClass::classify_token(sema, &token).map(IdentClass::definitions_no_ops);
if let Some(&[x]) = def.as_deref() {
return Some(x);
}
}
None
}

View file

@ -13,7 +13,7 @@ use syntax::{
use crate::{
helpers::item_name,
items_locator::{self, AssocItemSearch, DEFAULT_QUERY_SEARCH_LIMIT},
items_locator::{self, AssocSearchMode, DEFAULT_QUERY_SEARCH_LIMIT},
RootDatabase,
};
@ -317,7 +317,7 @@ fn path_applicable_imports(
// * improve the associated completion item matching and/or scoring to ensure no noisy completions appear
//
// see also an ignored test under FIXME comment in the qualify_path.rs module
AssocItemSearch::Exclude,
AssocSearchMode::Exclude,
Some(DEFAULT_QUERY_SEARCH_LIMIT.inner()),
)
.filter_map(|item| {
@ -334,7 +334,7 @@ fn path_applicable_imports(
sema,
current_crate,
path_candidate.name.clone(),
AssocItemSearch::Include,
AssocSearchMode::Include,
Some(DEFAULT_QUERY_SEARCH_LIMIT.inner()),
)
.filter_map(|item| {
@ -483,7 +483,7 @@ fn trait_applicable_items(
sema,
current_crate,
trait_candidate.assoc_item_name.clone(),
AssocItemSearch::AssocItemsOnly,
AssocSearchMode::AssocItemsOnly,
Some(DEFAULT_QUERY_SEARCH_LIMIT.inner()),
)
.filter_map(|input| item_as_assoc(db, input))

View file

@ -3,10 +3,7 @@
//! The main reason for this module to exist is the fact that project's items and dependencies' items
//! are located in different caches, with different APIs.
use either::Either;
use hir::{
import_map::{self, ImportKind},
AsAssocItem, Crate, ItemInNs, Semantics,
};
use hir::{import_map, AsAssocItem, Crate, ItemInNs, Semantics};
use limit::Limit;
use crate::{imports::import_assets::NameToImport, symbol_index, RootDatabase};
@ -14,23 +11,14 @@ use crate::{imports::import_assets::NameToImport, symbol_index, RootDatabase};
/// A value to use, when uncertain which limit to pick.
pub static DEFAULT_QUERY_SEARCH_LIMIT: Limit = Limit::new(40);
/// Three possible ways to search for the name in associated and/or other items.
#[derive(Debug, Clone, Copy)]
pub enum AssocItemSearch {
/// Search for the name in both associated and other items.
Include,
/// Search for the name in other items only.
Exclude,
/// Search for the name in the associated items only.
AssocItemsOnly,
}
pub use import_map::AssocSearchMode;
/// Searches for importable items with the given name in the crate and its dependencies.
pub fn items_with_name<'a>(
sema: &'a Semantics<'_, RootDatabase>,
krate: Crate,
name: NameToImport,
assoc_item_search: AssocItemSearch,
assoc_item_search: AssocSearchMode,
limit: Option<usize>,
) -> impl Iterator<Item = ItemInNs> + 'a {
let _p = profile::span("items_with_name").detail(|| {
@ -48,9 +36,7 @@ pub fn items_with_name<'a>(
let mut local_query = symbol_index::Query::new(exact_name.clone());
local_query.exact();
let external_query = import_map::Query::new(exact_name)
.name_only()
.search_mode(import_map::SearchMode::Equals);
let external_query = import_map::Query::new(exact_name);
(
local_query,
@ -61,17 +47,8 @@ pub fn items_with_name<'a>(
let mut local_query = symbol_index::Query::new(fuzzy_search_string.clone());
let mut external_query = import_map::Query::new(fuzzy_search_string.clone())
.search_mode(import_map::SearchMode::Fuzzy)
.name_only();
match assoc_item_search {
AssocItemSearch::Include => {}
AssocItemSearch::Exclude => {
external_query = external_query.exclude_import_kind(ImportKind::AssociatedItem);
}
AssocItemSearch::AssocItemsOnly => {
external_query = external_query.assoc_items_only();
}
}
.fuzzy()
.assoc_search_mode(assoc_item_search);
if fuzzy_search_string.to_lowercase() != fuzzy_search_string {
local_query.case_sensitive();
@ -93,13 +70,15 @@ pub fn items_with_name<'a>(
fn find_items<'a>(
sema: &'a Semantics<'_, RootDatabase>,
krate: Crate,
assoc_item_search: AssocItemSearch,
assoc_item_search: AssocSearchMode,
local_query: symbol_index::Query,
external_query: import_map::Query,
) -> impl Iterator<Item = ItemInNs> + 'a {
let _p = profile::span("find_items");
let db = sema.db;
// 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 {
@ -112,18 +91,15 @@ fn find_items<'a>(
let local_results = local_query
.search(&symbol_index::crate_symbols(db, krate))
.into_iter()
.filter_map(|local_candidate| match local_candidate.def {
hir::ModuleDef::Macro(macro_def) => Some(ItemInNs::Macros(macro_def)),
def => Some(ItemInNs::from(def)),
.filter(move |candidate| match assoc_item_search {
AssocSearchMode::Include => true,
AssocSearchMode::Exclude => candidate.def.as_assoc_item(db).is_none(),
AssocSearchMode::AssocItemsOnly => candidate.def.as_assoc_item(db).is_some(),
})
.map(|local_candidate| match local_candidate.def {
hir::ModuleDef::Macro(macro_def) => ItemInNs::Macros(macro_def),
def => ItemInNs::from(def),
});
external_importables.chain(local_results).filter(move |&item| match assoc_item_search {
AssocItemSearch::Include => true,
AssocItemSearch::Exclude => !is_assoc_item(item, sema.db),
AssocItemSearch::AssocItemsOnly => is_assoc_item(item, sema.db),
})
}
fn is_assoc_item(item: ItemInNs, db: &RootDatabase) -> bool {
item.as_module_def().and_then(|module_def| module_def.as_assoc_item(db)).is_some()
external_importables.chain(local_results)
}

View file

@ -200,8 +200,8 @@ impl RootDatabase {
hir_db::AstIdMapQuery
// hir_db::ParseMacroExpansionQuery
// hir_db::InternMacroCallQuery
hir_db::MacroArgTextQuery
hir_db::MacroDefQuery
hir_db::MacroArgNodeQuery
hir_db::DeclMacroExpanderQuery
// hir_db::MacroExpandQuery
hir_db::ExpandProcMacroQuery
hir_db::HygieneFrameQuery

View file

@ -195,7 +195,7 @@ fn postorder(item: &SyntaxNode) -> impl Iterator<Item = SyntaxNode> {
})
}
impl<'a> Ctx<'a> {
impl Ctx<'_> {
fn apply(&self, item: &SyntaxNode) {
// `transform_path` may update a node's parent and that would break the
// tree traversal. Thus all paths in the tree are collected into a vec

View file

@ -149,10 +149,8 @@ impl SearchScope {
let mut to_visit: Vec<_> = module.children(db).collect();
while let Some(module) = to_visit.pop() {
if let InFile { file_id, value: ModuleSource::SourceFile(_) } =
module.definition_source(db)
{
entries.insert(file_id.original_file(db), None);
if let Some(file_id) = module.as_source_file_id(db) {
entries.insert(file_id, None);
}
to_visit.extend(module.children(db));
}
@ -340,21 +338,21 @@ pub struct FindUsages<'a> {
search_self_mod: bool,
}
impl<'a> FindUsages<'a> {
impl FindUsages<'_> {
/// Enable searching for `Self` when the definition is a type or `self` for modules.
pub fn include_self_refs(mut self) -> FindUsages<'a> {
pub fn include_self_refs(mut self) -> Self {
self.include_self_kw_refs = def_to_ty(self.sema, &self.def);
self.search_self_mod = true;
self
}
/// Limit the search to a given [`SearchScope`].
pub fn in_scope(self, scope: SearchScope) -> FindUsages<'a> {
pub fn in_scope(self, scope: SearchScope) -> Self {
self.set_scope(Some(scope))
}
/// Limit the search to a given [`SearchScope`].
pub fn set_scope(mut self, scope: Option<SearchScope>) -> FindUsages<'a> {
pub fn set_scope(mut self, scope: Option<SearchScope>) -> Self {
assert!(self.scope.is_none());
self.scope = scope;
self

View file

@ -9,7 +9,10 @@ use crate::SnippetCap;
use base_db::{AnchoredPathBuf, FileId};
use nohash_hasher::IntMap;
use stdx::never;
use syntax::{algo, ast, ted, AstNode, SyntaxNode, SyntaxNodePtr, TextRange, TextSize};
use syntax::{
algo, ast, ted, AstNode, SyntaxElement, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange,
TextSize,
};
use text_edit::{TextEdit, TextEditBuilder};
#[derive(Default, Debug, Clone)]
@ -237,19 +240,31 @@ impl SourceChangeBuilder {
/// Adds a tabstop snippet to place the cursor before `node`
pub fn add_tabstop_before(&mut self, _cap: SnippetCap, node: impl AstNode) {
assert!(node.syntax().parent().is_some());
self.add_snippet(PlaceSnippet::Before(node.syntax().clone()));
self.add_snippet(PlaceSnippet::Before(node.syntax().clone().into()));
}
/// Adds a tabstop snippet to place the cursor after `node`
pub fn add_tabstop_after(&mut self, _cap: SnippetCap, node: impl AstNode) {
assert!(node.syntax().parent().is_some());
self.add_snippet(PlaceSnippet::After(node.syntax().clone()));
self.add_snippet(PlaceSnippet::After(node.syntax().clone().into()));
}
/// Adds a tabstop snippet to place the cursor before `token`
pub fn add_tabstop_before_token(&mut self, _cap: SnippetCap, token: SyntaxToken) {
assert!(token.parent().is_some());
self.add_snippet(PlaceSnippet::Before(token.clone().into()));
}
/// Adds a tabstop snippet to place the cursor after `token`
pub fn add_tabstop_after_token(&mut self, _cap: SnippetCap, token: SyntaxToken) {
assert!(token.parent().is_some());
self.add_snippet(PlaceSnippet::After(token.clone().into()));
}
/// Adds a snippet to move the cursor selected over `node`
pub fn add_placeholder_snippet(&mut self, _cap: SnippetCap, node: impl AstNode) {
assert!(node.syntax().parent().is_some());
self.add_snippet(PlaceSnippet::Over(node.syntax().clone()))
self.add_snippet(PlaceSnippet::Over(node.syntax().clone().into()))
}
fn add_snippet(&mut self, snippet: PlaceSnippet) {
@ -282,38 +297,40 @@ impl From<FileSystemEdit> for SourceChange {
}
enum PlaceSnippet {
/// Place a tabstop before a node
Before(SyntaxNode),
/// Place a tabstop before a node
After(SyntaxNode),
/// Place a placeholder snippet in place of the node
Over(SyntaxNode),
/// Place a tabstop before an element
Before(SyntaxElement),
/// Place a tabstop before an element
After(SyntaxElement),
/// Place a placeholder snippet in place of the element
Over(SyntaxElement),
}
impl PlaceSnippet {
/// Places the snippet before or over a node with the given tab stop index
/// Places the snippet before or over an element with the given tab stop index
fn place(self, order: usize) {
// ensure the target node is still attached
// ensure the target element is still attached
match &self {
PlaceSnippet::Before(node) | PlaceSnippet::After(node) | PlaceSnippet::Over(node) => {
// node should still be in the tree, but if it isn't
PlaceSnippet::Before(element)
| PlaceSnippet::After(element)
| PlaceSnippet::Over(element) => {
// element should still be in the tree, but if it isn't
// then it's okay to just ignore this place
if stdx::never!(node.parent().is_none()) {
if stdx::never!(element.parent().is_none()) {
return;
}
}
}
match self {
PlaceSnippet::Before(node) => {
ted::insert_raw(ted::Position::before(&node), Self::make_tab_stop(order));
PlaceSnippet::Before(element) => {
ted::insert_raw(ted::Position::before(&element), Self::make_tab_stop(order));
}
PlaceSnippet::After(node) => {
ted::insert_raw(ted::Position::after(&node), Self::make_tab_stop(order));
PlaceSnippet::After(element) => {
ted::insert_raw(ted::Position::after(&element), Self::make_tab_stop(order));
}
PlaceSnippet::Over(node) => {
let position = ted::Position::before(&node);
node.detach();
PlaceSnippet::Over(element) => {
let position = ted::Position::before(&element);
element.detach();
let snippet = ast::SourceFile::parse(&format!("${{{order}:_}}"))
.syntax_node()
@ -321,7 +338,7 @@ impl PlaceSnippet {
let placeholder =
snippet.descendants().find_map(ast::UnderscoreExpr::cast).unwrap();
ted::replace(placeholder.syntax(), node);
ted::replace(placeholder.syntax(), element);
ted::insert_raw(position, snippet);
}