mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-29 06:23:25 +00:00
Merge #7357
7357: Dont show runnables from nested mods r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
6cf3d669e2
2 changed files with 81 additions and 23 deletions
|
@ -9,6 +9,7 @@ use syntax::{
|
||||||
ast::{self, AstNode, AttrsOwner},
|
ast::{self, AstNode, AttrsOwner},
|
||||||
match_ast, SyntaxNode,
|
match_ast, SyntaxNode,
|
||||||
};
|
};
|
||||||
|
use test_utils::mark;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
display::{ToNav, TryToNav},
|
display::{ToNav, TryToNav},
|
||||||
|
@ -96,28 +97,26 @@ impl Runnable {
|
||||||
pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
|
pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
|
||||||
let sema = Semantics::new(db);
|
let sema = Semantics::new(db);
|
||||||
let module = match sema.to_module_def(file_id) {
|
let module = match sema.to_module_def(file_id) {
|
||||||
None => return vec![],
|
None => return Vec::new(),
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
};
|
};
|
||||||
|
|
||||||
runnables_mod(&sema, module)
|
let mut res = Vec::new();
|
||||||
|
runnables_mod(&sema, &mut res, module);
|
||||||
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn runnables_mod(sema: &Semantics<RootDatabase>, module: hir::Module) -> Vec<Runnable> {
|
fn runnables_mod(sema: &Semantics<RootDatabase>, acc: &mut Vec<Runnable>, module: hir::Module) {
|
||||||
let mut res: Vec<Runnable> = module
|
acc.extend(module.declarations(sema.db).into_iter().filter_map(|def| {
|
||||||
.declarations(sema.db)
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(|def| {
|
|
||||||
let runnable = match def {
|
let runnable = match def {
|
||||||
hir::ModuleDef::Module(it) => runnable_mod(&sema, it),
|
hir::ModuleDef::Module(it) => runnable_mod(&sema, it),
|
||||||
hir::ModuleDef::Function(it) => runnable_fn(&sema, it),
|
hir::ModuleDef::Function(it) => runnable_fn(&sema, it),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
runnable.or_else(|| module_def_doctest(&sema, def))
|
runnable.or_else(|| module_def_doctest(&sema, def))
|
||||||
})
|
}));
|
||||||
.collect();
|
|
||||||
|
|
||||||
res.extend(module.impl_defs(sema.db).into_iter().flat_map(|it| it.items(sema.db)).filter_map(
|
acc.extend(module.impl_defs(sema.db).into_iter().flat_map(|it| it.items(sema.db)).filter_map(
|
||||||
|def| match def {
|
|def| match def {
|
||||||
hir::AssocItem::Function(it) => {
|
hir::AssocItem::Function(it) => {
|
||||||
runnable_fn(&sema, it).or_else(|| module_def_doctest(&sema, it.into()))
|
runnable_fn(&sema, it).or_else(|| module_def_doctest(&sema, it.into()))
|
||||||
|
@ -127,12 +126,14 @@ fn runnables_mod(sema: &Semantics<RootDatabase>, module: hir::Module) -> Vec<Run
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
res.extend(module.declarations(sema.db).into_iter().flat_map(|def| match def {
|
for def in module.declarations(sema.db) {
|
||||||
hir::ModuleDef::Module(it) => runnables_mod(sema, it),
|
if let hir::ModuleDef::Module(submodule) = def {
|
||||||
_ => vec![],
|
match submodule.definition_source(sema.db).value {
|
||||||
}));
|
hir::ModuleSource::Module(_) => runnables_mod(sema, acc, submodule),
|
||||||
|
hir::ModuleSource::SourceFile(_) => mark::hit!(dont_recurse_in_outline_submodules),
|
||||||
res
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn runnable_fn(sema: &Semantics<RootDatabase>, def: hir::Function) -> Option<Runnable> {
|
pub(crate) fn runnable_fn(sema: &Semantics<RootDatabase>, def: hir::Function) -> Option<Runnable> {
|
||||||
|
@ -326,6 +327,7 @@ fn has_test_function_or_multiple_test_submodules(
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use expect_test::{expect, Expect};
|
use expect_test::{expect, Expect};
|
||||||
|
use test_utils::mark;
|
||||||
|
|
||||||
use crate::fixture;
|
use crate::fixture;
|
||||||
|
|
||||||
|
@ -1050,4 +1052,25 @@ mod tests {
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn dont_recurse_in_outline_submodules() {
|
||||||
|
mark::check!(dont_recurse_in_outline_submodules);
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
//- /lib.rs
|
||||||
|
$0
|
||||||
|
mod m;
|
||||||
|
//- /m.rs
|
||||||
|
mod tests {
|
||||||
|
#[test]
|
||||||
|
fn t() {}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
&[],
|
||||||
|
expect![[r#"
|
||||||
|
[]
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,6 +280,9 @@ Prefer `Default` even it has to be implemented manually.
|
||||||
|
|
||||||
**Rationale:** less typing in the common case, uniformity.
|
**Rationale:** less typing in the common case, uniformity.
|
||||||
|
|
||||||
|
Use `Vec::new` rather than `vec![]`. **Rationale:** uniformity, strength
|
||||||
|
reduction.
|
||||||
|
|
||||||
## Functions Over Objects
|
## Functions Over Objects
|
||||||
|
|
||||||
Avoid creating "doer" objects.
|
Avoid creating "doer" objects.
|
||||||
|
@ -418,12 +421,44 @@ fn frobnicate(s: &str) {
|
||||||
**Rationale:** reveals the costs.
|
**Rationale:** reveals the costs.
|
||||||
It is also more efficient when the caller already owns the allocation.
|
It is also more efficient when the caller already owns the allocation.
|
||||||
|
|
||||||
## Collection types
|
## Collection Types
|
||||||
|
|
||||||
Prefer `rustc_hash::FxHashMap` and `rustc_hash::FxHashSet` instead of the ones in `std::collections`.
|
Prefer `rustc_hash::FxHashMap` and `rustc_hash::FxHashSet` instead of the ones in `std::collections`.
|
||||||
|
|
||||||
**Rationale:** they use a hasher that's significantly faster and using them consistently will reduce code size by some small amount.
|
**Rationale:** they use a hasher that's significantly faster and using them consistently will reduce code size by some small amount.
|
||||||
|
|
||||||
|
## Avoid Intermediate Collections
|
||||||
|
|
||||||
|
When writing a recursive function to compute a sets of things, use an accumulator parameter instead of returning a fresh collection.
|
||||||
|
Accumulator goes first in the list of arguments.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// GOOD
|
||||||
|
pub fn reachable_nodes(node: Node) -> FxHashSet<Node> {
|
||||||
|
let mut res = FxHashSet::default();
|
||||||
|
go(&mut res, node);
|
||||||
|
res
|
||||||
|
}
|
||||||
|
fn go(acc: &mut FxHashSet<Node>, node: Node) {
|
||||||
|
acc.insert(node);
|
||||||
|
for n in node.neighbors() {
|
||||||
|
go(acc, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BAD
|
||||||
|
pub fn reachable_nodes(node: Node) -> FxHashSet<Node> {
|
||||||
|
let mut res = FxHashSet::default();
|
||||||
|
res.insert(node);
|
||||||
|
for n in node.neighbors() {
|
||||||
|
res.extend(reachable_nodes(n));
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Rational:** re-use allocations, accumulator style is more concise for complex cases.
|
||||||
|
|
||||||
# Style
|
# Style
|
||||||
|
|
||||||
## Order of Imports
|
## Order of Imports
|
||||||
|
|
Loading…
Reference in a new issue