mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Merge pull request #21906 from Young-Flash/master
feat: exclude refs(find all refs) from deps and stdlib
This commit is contained in:
@@ -449,6 +449,8 @@ pub fn usages<'a>(self, sema: &'a Semantics<'_, RootDatabase>) -> FindUsages<'a>
|
||||
scope: None,
|
||||
include_self_kw_refs: None,
|
||||
search_self_mod: false,
|
||||
included_categories: ReferenceCategory::all(),
|
||||
exclude_library_files: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -465,6 +467,10 @@ pub struct FindUsages<'a> {
|
||||
include_self_kw_refs: Option<hir::Type<'a>>,
|
||||
/// whether to search for the `self` module
|
||||
search_self_mod: bool,
|
||||
/// categories to include while collecting usages
|
||||
included_categories: ReferenceCategory,
|
||||
/// whether to skip files from library source roots
|
||||
exclude_library_files: bool,
|
||||
}
|
||||
|
||||
impl<'a> FindUsages<'a> {
|
||||
@@ -495,6 +501,16 @@ pub fn with_rename(mut self, rename: Option<&'a Rename>) -> Self {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_included_categories(mut self, categories: ReferenceCategory) -> Self {
|
||||
self.included_categories = categories;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_exclude_library_files(mut self, exclude_library_files: bool) -> Self {
|
||||
self.exclude_library_files = exclude_library_files;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn at_least_one(&self) -> bool {
|
||||
let mut found = false;
|
||||
self.search(&mut |_, _| {
|
||||
@@ -516,14 +532,21 @@ pub fn all(self) -> UsageSearchResult {
|
||||
fn scope_files<'b>(
|
||||
db: &'b RootDatabase,
|
||||
scope: &'b SearchScope,
|
||||
exclude_library_files: bool,
|
||||
) -> impl Iterator<Item = (Arc<str>, EditionedFileId, TextRange)> + 'b {
|
||||
scope.entries.iter().map(|(&file_id, &search_range)| {
|
||||
let text = db.file_text(file_id.file_id(db)).text(db);
|
||||
let search_range =
|
||||
search_range.unwrap_or_else(|| TextRange::up_to(TextSize::of(&**text)));
|
||||
scope
|
||||
.entries
|
||||
.iter()
|
||||
.filter(move |(file_id, _)| {
|
||||
!exclude_library_files || !is_library_file(db, file_id.file_id(db))
|
||||
})
|
||||
.map(|(&file_id, &search_range)| {
|
||||
let text = db.file_text(file_id.file_id(db)).text(db);
|
||||
let search_range =
|
||||
search_range.unwrap_or_else(|| TextRange::up_to(TextSize::of(&**text)));
|
||||
|
||||
(text.clone(), file_id, search_range)
|
||||
})
|
||||
(text.clone(), file_id, search_range)
|
||||
})
|
||||
}
|
||||
|
||||
fn match_indices<'b>(
|
||||
@@ -649,6 +672,7 @@ fn has_any_name(node: &SyntaxNode, mut predicate: impl FnMut(&str) -> bool) -> b
|
||||
fn collect_possible_aliases(
|
||||
sema: &Semantics<'_, RootDatabase>,
|
||||
container: Adt,
|
||||
exclude_library_files: bool,
|
||||
) -> Option<(FxHashSet<SmolStr>, Vec<FileRangeWrapper<EditionedFileId>>)> {
|
||||
fn insert_type_alias(
|
||||
db: &RootDatabase,
|
||||
@@ -682,9 +706,11 @@ fn insert_type_alias(
|
||||
};
|
||||
|
||||
let finder = Finder::new(current_to_process.as_bytes());
|
||||
for (file_text, file_id, search_range) in
|
||||
FindUsages::scope_files(db, ¤t_to_process_search_scope)
|
||||
{
|
||||
for (file_text, file_id, search_range) in FindUsages::scope_files(
|
||||
db,
|
||||
¤t_to_process_search_scope,
|
||||
exclude_library_files,
|
||||
) {
|
||||
let tree = LazyCell::new(move || sema.parse(file_id).syntax().clone());
|
||||
|
||||
for offset in FindUsages::match_indices(&file_text, &finder, search_range) {
|
||||
@@ -869,7 +895,7 @@ fn search(
|
||||
}
|
||||
|
||||
let Some((container_possible_aliases, is_possibly_self)) =
|
||||
collect_possible_aliases(self.sema, container)
|
||||
collect_possible_aliases(self.sema, container, self.exclude_library_files)
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
@@ -906,7 +932,7 @@ fn search(
|
||||
self,
|
||||
&finder,
|
||||
name,
|
||||
FindUsages::scope_files(self.sema.db, search_scope),
|
||||
FindUsages::scope_files(self.sema.db, search_scope, self.exclude_library_files),
|
||||
|path, name_position| {
|
||||
has_any_name(path, |name| container_possible_aliases.contains(name))
|
||||
&& !self_positions.contains(&name_position)
|
||||
@@ -931,6 +957,9 @@ pub fn search(&self, sink: &mut dyn FnMut(EditionedFileId, FileReference) -> boo
|
||||
Some(scope) => base.intersection(scope),
|
||||
}
|
||||
};
|
||||
if search_scope.entries.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let name = match (self.rename, self.def) {
|
||||
(Some(rename), _) => {
|
||||
@@ -982,7 +1011,9 @@ pub fn search(&self, sink: &mut dyn FnMut(EditionedFileId, FileReference) -> boo
|
||||
let finder = &Finder::new(name);
|
||||
let include_self_kw_refs =
|
||||
self.include_self_kw_refs.as_ref().map(|ty| (ty, Finder::new("Self")));
|
||||
for (text, file_id, search_range) in Self::scope_files(sema.db, &search_scope) {
|
||||
for (text, file_id, search_range) in
|
||||
Self::scope_files(sema.db, &search_scope, self.exclude_library_files)
|
||||
{
|
||||
let tree = LazyCell::new(move || sema.parse(file_id).syntax().clone());
|
||||
|
||||
// Search for occurrences of the items name
|
||||
@@ -1039,7 +1070,9 @@ pub fn search(&self, sink: &mut dyn FnMut(EditionedFileId, FileReference) -> boo
|
||||
let is_crate_root = module.is_crate_root(self.sema.db).then(|| Finder::new("crate"));
|
||||
let finder = &Finder::new("super");
|
||||
|
||||
for (text, file_id, search_range) in Self::scope_files(sema.db, &scope) {
|
||||
for (text, file_id, search_range) in
|
||||
Self::scope_files(sema.db, &scope, self.exclude_library_files)
|
||||
{
|
||||
self.sema.db.unwind_if_revision_cancelled();
|
||||
|
||||
let tree = LazyCell::new(move || sema.parse(file_id).syntax().clone());
|
||||
@@ -1118,6 +1151,10 @@ fn found_self_ty_name_ref(
|
||||
name_ref: &ast::NameRef,
|
||||
sink: &mut dyn FnMut(EditionedFileId, FileReference) -> bool,
|
||||
) -> bool {
|
||||
if self.is_excluded_name_ref(name_ref) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// See https://github.com/rust-lang/rust-analyzer/pull/15864/files/e0276dc5ddc38c65240edb408522bb869f15afb4#r1389848845
|
||||
let ty_eq = |ty: hir::Type<'_>| match (ty.as_adt(), self_ty.as_adt()) {
|
||||
(Some(ty), Some(self_ty)) => ty == self_ty,
|
||||
@@ -1146,6 +1183,10 @@ fn found_self_module_name_ref(
|
||||
name_ref: &ast::NameRef,
|
||||
sink: &mut dyn FnMut(EditionedFileId, FileReference) -> bool,
|
||||
) -> bool {
|
||||
if self.is_excluded_name_ref(name_ref) {
|
||||
return false;
|
||||
}
|
||||
|
||||
match NameRefClass::classify(self.sema, name_ref) {
|
||||
Some(NameRefClass::Definition(def @ Definition::Module(_), _)) if def == self.def => {
|
||||
let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax());
|
||||
@@ -1210,6 +1251,10 @@ fn found_name_ref(
|
||||
name_ref: &ast::NameRef,
|
||||
sink: &mut dyn FnMut(EditionedFileId, FileReference) -> bool,
|
||||
) -> bool {
|
||||
if self.is_excluded_name_ref(name_ref) {
|
||||
return false;
|
||||
}
|
||||
|
||||
match NameRefClass::classify(self.sema, name_ref) {
|
||||
Some(NameRefClass::Definition(def, _))
|
||||
if self.def == def
|
||||
@@ -1282,6 +1327,13 @@ fn found_name_ref(
|
||||
}
|
||||
}
|
||||
|
||||
fn is_excluded_name_ref(&self, name_ref: &ast::NameRef) -> bool {
|
||||
(!self.included_categories.contains(ReferenceCategory::TEST)
|
||||
&& is_name_ref_in_test(self.sema, name_ref))
|
||||
|| (!self.included_categories.contains(ReferenceCategory::IMPORT)
|
||||
&& is_name_ref_in_import(name_ref))
|
||||
}
|
||||
|
||||
fn found_name(
|
||||
&self,
|
||||
name: &ast::Name,
|
||||
@@ -1408,3 +1460,8 @@ fn is_name_ref_in_test(sema: &Semantics<'_, RootDatabase>, name_ref: &ast::NameR
|
||||
None => false,
|
||||
})
|
||||
}
|
||||
|
||||
fn is_library_file(db: &RootDatabase, file_id: span::FileId) -> bool {
|
||||
let source_root = db.file_source_root(file_id).source_root_id(db);
|
||||
db.source_root(source_root).source_root(db).is_library
|
||||
}
|
||||
|
||||
@@ -216,7 +216,12 @@ pub(crate) fn resolve_annotation(
|
||||
*data = find_all_refs(
|
||||
&Semantics::new(db),
|
||||
pos,
|
||||
&FindAllRefsConfig { search_scope: None, ra_fixture: config.ra_fixture },
|
||||
&FindAllRefsConfig {
|
||||
search_scope: None,
|
||||
ra_fixture: config.ra_fixture,
|
||||
exclude_imports: false,
|
||||
exclude_tests: false,
|
||||
},
|
||||
)
|
||||
.map(|result| {
|
||||
result
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
use hir::{PathResolution, Semantics};
|
||||
use ide_db::{
|
||||
FileId, RootDatabase,
|
||||
base_db::SourceDatabase,
|
||||
defs::{Definition, NameClass, NameRefClass},
|
||||
helpers::pick_best_token,
|
||||
ra_fixture::{RaFixtureConfig, UpmapFromRaFixture},
|
||||
@@ -91,6 +92,8 @@ pub struct Declaration {
|
||||
pub struct FindAllRefsConfig<'a> {
|
||||
pub search_scope: Option<SearchScope>,
|
||||
pub ra_fixture: RaFixtureConfig<'a>,
|
||||
pub exclude_imports: bool,
|
||||
pub exclude_tests: bool,
|
||||
}
|
||||
|
||||
/// Find all references to the item at the given position.
|
||||
@@ -125,10 +128,23 @@ pub(crate) fn find_all_refs(
|
||||
) -> Option<Vec<ReferenceSearchResult>> {
|
||||
let _p = tracing::info_span!("find_all_refs").entered();
|
||||
let syntax = sema.parse_guess_edition(position.file_id).syntax().clone();
|
||||
let exclude_library_refs = !is_library_file(sema.db, position.file_id);
|
||||
let make_searcher = |literal_search: bool| {
|
||||
move |def: Definition| {
|
||||
let mut usages =
|
||||
def.usages(sema).set_scope(config.search_scope.as_ref()).include_self_refs().all();
|
||||
let mut included_categories = ReferenceCategory::all();
|
||||
if config.exclude_imports {
|
||||
included_categories.remove(ReferenceCategory::IMPORT);
|
||||
}
|
||||
if config.exclude_tests {
|
||||
included_categories.remove(ReferenceCategory::TEST);
|
||||
}
|
||||
let mut usages = def
|
||||
.usages(sema)
|
||||
.set_scope(config.search_scope.as_ref())
|
||||
.set_included_categories(included_categories)
|
||||
.set_exclude_library_files(exclude_library_refs)
|
||||
.include_self_refs()
|
||||
.all();
|
||||
if literal_search {
|
||||
retain_adt_literal_usages(&mut usages, def, sema);
|
||||
}
|
||||
@@ -207,6 +223,11 @@ pub(crate) fn find_all_refs(
|
||||
}
|
||||
}
|
||||
|
||||
fn is_library_file(db: &RootDatabase, file_id: FileId) -> bool {
|
||||
let source_root = db.file_source_root(file_id).source_root_id(db);
|
||||
db.source_root(source_root).source_root(db).is_library
|
||||
}
|
||||
|
||||
pub(crate) fn find_defs(
|
||||
sema: &Semantics<'_, RootDatabase>,
|
||||
syntax: &SyntaxNode,
|
||||
@@ -469,7 +490,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn exclude_tests() {
|
||||
check(
|
||||
check_with_filters(
|
||||
r#"
|
||||
fn test_func() {}
|
||||
|
||||
@@ -482,6 +503,8 @@ fn test() {
|
||||
test_func();
|
||||
}
|
||||
"#,
|
||||
false,
|
||||
false,
|
||||
expect![[r#"
|
||||
test_func Function FileId(0) 0..17 3..12
|
||||
|
||||
@@ -490,7 +513,7 @@ fn test() {
|
||||
"#]],
|
||||
);
|
||||
|
||||
check(
|
||||
check_with_filters(
|
||||
r#"
|
||||
fn test_func() {}
|
||||
|
||||
@@ -503,6 +526,8 @@ fn test() {
|
||||
test_func();
|
||||
}
|
||||
"#,
|
||||
false,
|
||||
false,
|
||||
expect![[r#"
|
||||
test_func Function FileId(0) 0..17 3..12
|
||||
|
||||
@@ -510,6 +535,133 @@ fn test() {
|
||||
FileId(0) 96..105 test
|
||||
"#]],
|
||||
);
|
||||
|
||||
check_with_filters(
|
||||
r#"
|
||||
fn test_func() {}
|
||||
|
||||
fn func() {
|
||||
test_func$0();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
test_func();
|
||||
}
|
||||
"#,
|
||||
false,
|
||||
true,
|
||||
expect![[r#"
|
||||
test_func Function FileId(0) 0..17 3..12
|
||||
|
||||
FileId(0) 35..44
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exclude_library_refs_filtering() {
|
||||
// exclude refs in 3rd party lib
|
||||
check_with_filters(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:dep
|
||||
use dep::foo;
|
||||
|
||||
fn main() {
|
||||
foo$0();
|
||||
}
|
||||
|
||||
//- /dep/lib.rs crate:dep new_source_root:library
|
||||
pub fn foo() {}
|
||||
|
||||
pub fn also_calls_foo() {
|
||||
foo();
|
||||
}
|
||||
"#,
|
||||
false,
|
||||
false,
|
||||
expect![[r#"
|
||||
foo Function FileId(1) 0..15 7..10
|
||||
|
||||
FileId(0) 9..12 import
|
||||
FileId(0) 31..34
|
||||
"#]],
|
||||
);
|
||||
|
||||
// exclude refs in stdlib
|
||||
check_with_filters(
|
||||
r#"
|
||||
//- minicore: option
|
||||
fn main() {
|
||||
let _ = core::option::Option::Some$0(0);
|
||||
}
|
||||
"#,
|
||||
false,
|
||||
false,
|
||||
expect![[r#"
|
||||
Some Variant FileId(1) 5999..6031 6024..6028
|
||||
|
||||
FileId(0) 46..50
|
||||
"#]],
|
||||
);
|
||||
|
||||
// keep refs in local lib
|
||||
check_with_filters(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:dep
|
||||
use dep::foo;
|
||||
|
||||
fn main() {
|
||||
foo$0();
|
||||
}
|
||||
|
||||
//- /dep/lib.rs crate:dep
|
||||
pub fn foo() {}
|
||||
|
||||
pub fn also_calls_foo() {
|
||||
foo();
|
||||
}
|
||||
"#,
|
||||
false,
|
||||
false,
|
||||
expect![[r#"
|
||||
foo Function FileId(1) 0..15 7..10
|
||||
|
||||
FileId(0) 9..12 import
|
||||
FileId(0) 31..34
|
||||
FileId(1) 47..50
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn find_refs_from_library_source_keeps_library_refs() {
|
||||
check_with_filters(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:dep
|
||||
use dep::foo;
|
||||
|
||||
fn main() {
|
||||
foo();
|
||||
}
|
||||
|
||||
//- /dep/lib.rs crate:dep new_source_root:library
|
||||
pub fn foo$0() {}
|
||||
|
||||
pub fn also_calls_foo() {
|
||||
foo();
|
||||
}
|
||||
"#,
|
||||
false,
|
||||
false,
|
||||
expect![[r#"
|
||||
foo Function FileId(1) 0..15 7..10
|
||||
|
||||
FileId(0) 9..12 import
|
||||
FileId(0) 31..34
|
||||
FileId(1) 47..50
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1556,18 +1708,39 @@ fn main() {
|
||||
}
|
||||
|
||||
fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
|
||||
check_with_scope(ra_fixture, None, expect)
|
||||
check_with_filters(ra_fixture, false, false, expect)
|
||||
}
|
||||
|
||||
fn check_with_filters(
|
||||
#[rust_analyzer::rust_fixture] ra_fixture: &str,
|
||||
exclude_imports: bool,
|
||||
exclude_tests: bool,
|
||||
expect: Expect,
|
||||
) {
|
||||
check_with_scope_and_filters(ra_fixture, None, exclude_imports, exclude_tests, expect)
|
||||
}
|
||||
|
||||
fn check_with_scope(
|
||||
#[rust_analyzer::rust_fixture] ra_fixture: &str,
|
||||
search_scope: Option<&mut dyn FnMut(&RootDatabase) -> SearchScope>,
|
||||
expect: Expect,
|
||||
) {
|
||||
check_with_scope_and_filters(ra_fixture, search_scope, false, false, expect)
|
||||
}
|
||||
|
||||
fn check_with_scope_and_filters(
|
||||
#[rust_analyzer::rust_fixture] ra_fixture: &str,
|
||||
search_scope: Option<&mut dyn FnMut(&RootDatabase) -> SearchScope>,
|
||||
exclude_imports: bool,
|
||||
exclude_tests: bool,
|
||||
expect: Expect,
|
||||
) {
|
||||
let (analysis, pos) = fixture::position(ra_fixture);
|
||||
let config = FindAllRefsConfig {
|
||||
search_scope: search_scope.map(|it| it(&analysis.db)),
|
||||
ra_fixture: RaFixtureConfig::default(),
|
||||
exclude_imports,
|
||||
exclude_tests,
|
||||
};
|
||||
let refs = analysis.find_all_refs(pos, &config).unwrap().unwrap();
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
use ide::{
|
||||
AssistKind, AssistResolveStrategy, Cancellable, CompletionFieldsToResolve, FilePosition,
|
||||
FileRange, FileStructureConfig, FindAllRefsConfig, HoverAction, HoverGotoTypeData,
|
||||
InlayFieldsToResolve, Query, RangeInfo, ReferenceCategory, Runnable, RunnableKind,
|
||||
SingleResolve, SourceChange, TextEdit,
|
||||
InlayFieldsToResolve, Query, RangeInfo, Runnable, RunnableKind, SingleResolve, SourceChange,
|
||||
TextEdit,
|
||||
};
|
||||
use ide_db::{FxHashMap, SymbolKind};
|
||||
use itertools::Itertools;
|
||||
@@ -1396,12 +1396,13 @@ pub(crate) fn handle_references(
|
||||
|
||||
let exclude_imports = snap.config.find_all_refs_exclude_imports();
|
||||
let exclude_tests = snap.config.find_all_refs_exclude_tests();
|
||||
|
||||
let Some(refs) = snap.analysis.find_all_refs(
|
||||
position,
|
||||
&FindAllRefsConfig {
|
||||
search_scope: None,
|
||||
ra_fixture: snap.config.ra_fixture(snap.minicore()),
|
||||
exclude_imports,
|
||||
exclude_tests,
|
||||
},
|
||||
)?
|
||||
else {
|
||||
@@ -1423,12 +1424,7 @@ pub(crate) fn handle_references(
|
||||
refs.references
|
||||
.into_iter()
|
||||
.flat_map(|(file_id, refs)| {
|
||||
refs.into_iter()
|
||||
.filter(|&(_, category)| {
|
||||
(!exclude_imports || !category.contains(ReferenceCategory::IMPORT))
|
||||
&& (!exclude_tests || !category.contains(ReferenceCategory::TEST))
|
||||
})
|
||||
.map(move |(range, _)| FileRange { file_id, range })
|
||||
refs.into_iter().map(move |(range, _)| FileRange { file_id, range })
|
||||
})
|
||||
.chain(decl)
|
||||
})
|
||||
@@ -2211,7 +2207,10 @@ fn show_ref_command_link(
|
||||
*position,
|
||||
&FindAllRefsConfig {
|
||||
search_scope: None,
|
||||
|
||||
ra_fixture: snap.config.ra_fixture(snap.minicore()),
|
||||
exclude_imports: snap.config.find_all_refs_exclude_imports(),
|
||||
exclude_tests: snap.config.find_all_refs_exclude_tests(),
|
||||
},
|
||||
)
|
||||
.unwrap_or(None)
|
||||
|
||||
Reference in New Issue
Block a user