Skip to content

Commit ce938fe

Browse files
authored
[ty] Speedup project file discovery (#19913)
1 parent 7f8f1ab commit ce938fe

File tree

3 files changed

+33
-41
lines changed

3 files changed

+33
-41
lines changed

crates/ruff_db/src/files.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,12 @@ impl Files {
8787
.system_by_path
8888
.entry(absolute.clone())
8989
.or_insert_with(|| {
90-
tracing::trace!("Adding file '{path}'");
91-
9290
let metadata = db.system().path_metadata(path);
91+
92+
tracing::trace!("Adding file '{absolute}'");
93+
9394
let durability = self
94-
.root(db, path)
95+
.root(db, &absolute)
9596
.map_or(Durability::default(), |root| root.durability(db));
9697

9798
let builder = File::builder(FilePath::System(absolute))

crates/ty_project/src/db.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ mod changes;
2121
#[salsa::db]
2222
pub trait Db: SemanticDb {
2323
fn project(&self) -> Project;
24+
25+
fn dyn_clone(&self) -> Box<dyn Db>;
2426
}
2527

2628
#[salsa::db]
@@ -484,6 +486,10 @@ impl Db for ProjectDatabase {
484486
fn project(&self) -> Project {
485487
self.project.unwrap()
486488
}
489+
490+
fn dyn_clone(&self) -> Box<dyn Db> {
491+
Box::new(self.clone())
492+
}
487493
}
488494

489495
#[cfg(feature = "format")]
@@ -611,6 +617,10 @@ pub(crate) mod tests {
611617
fn project(&self) -> Project {
612618
self.project.unwrap()
613619
}
620+
621+
fn dyn_clone(&self) -> Box<dyn Db> {
622+
Box::new(self.clone())
623+
}
614624
}
615625

616626
#[salsa::db]

crates/ty_project/src/walk.rs

Lines changed: 19 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use ruff_db::files::{File, system_path_to_file};
44
use ruff_db::system::walk_directory::{ErrorKind, WalkDirectoryBuilder, WalkState};
55
use ruff_db::system::{SystemPath, SystemPathBuf};
66
use ruff_python_ast::PySourceType;
7-
use rustc_hash::{FxBuildHasher, FxHashSet};
7+
use rustc_hash::FxHashSet;
88
use std::path::PathBuf;
99
use thiserror::Error;
1010

@@ -163,20 +163,24 @@ impl<'a> ProjectFilesWalker<'a> {
163163

164164
/// Walks the project paths and collects the paths of all files that
165165
/// are included in the project.
166-
pub(crate) fn walk_paths(self) -> (Vec<SystemPathBuf>, Vec<IOErrorDiagnostic>) {
167-
let paths = std::sync::Mutex::new(Vec::new());
166+
pub(crate) fn collect_vec(self, db: &dyn Db) -> (Vec<File>, Vec<IOErrorDiagnostic>) {
167+
let files = std::sync::Mutex::new(Vec::new());
168168
let diagnostics = std::sync::Mutex::new(Vec::new());
169169

170170
self.walker.run(|| {
171-
Box::new(|entry| {
171+
let db = db.dyn_clone();
172+
let filter = &self.filter;
173+
let files = &files;
174+
let diagnostics = &diagnostics;
175+
176+
Box::new(move |entry| {
172177
match entry {
173178
Ok(entry) => {
174179
// Skip excluded directories unless they were explicitly passed to the walker
175180
// (which is the case passed to `ty check <paths>`).
176181
if entry.file_type().is_directory() {
177182
if entry.depth() > 0 {
178-
let directory_included = self
179-
.filter
183+
let directory_included = filter
180184
.is_directory_included(entry.path(), GlobFilterCheckMode::TopDown);
181185
return match directory_included {
182186
IncludeResult::Included => WalkState::Continue,
@@ -210,8 +214,7 @@ impl<'a> ProjectFilesWalker<'a> {
210214
// For all files, except the ones that were explicitly passed to the walker (CLI),
211215
// check if they're included in the project.
212216
if entry.depth() > 0 {
213-
match self
214-
.filter
217+
match filter
215218
.is_file_included(entry.path(), GlobFilterCheckMode::TopDown)
216219
{
217220
IncludeResult::Included => {},
@@ -232,8 +235,11 @@ impl<'a> ProjectFilesWalker<'a> {
232235
}
233236
}
234237

235-
let mut paths = paths.lock().unwrap();
236-
paths.push(entry.into_path());
238+
// If this returns `Err`, then the file was deleted between now and when the walk callback was called.
239+
// We can ignore this.
240+
if let Ok(file) = system_path_to_file(&*db, entry.path()) {
241+
files.lock().unwrap().push(file);
242+
}
237243
}
238244
}
239245
Err(error) => match error.kind() {
@@ -274,39 +280,14 @@ impl<'a> ProjectFilesWalker<'a> {
274280
});
275281

276282
(
277-
paths.into_inner().unwrap(),
283+
files.into_inner().unwrap(),
278284
diagnostics.into_inner().unwrap(),
279285
)
280286
}
281287

282-
pub(crate) fn collect_vec(self, db: &dyn Db) -> (Vec<File>, Vec<IOErrorDiagnostic>) {
283-
let (paths, diagnostics) = self.walk_paths();
284-
285-
(
286-
paths
287-
.into_iter()
288-
.filter_map(move |path| {
289-
// If this returns `None`, then the file was deleted between the `walk_directory` call and now.
290-
// We can ignore this.
291-
system_path_to_file(db, &path).ok()
292-
})
293-
.collect(),
294-
diagnostics,
295-
)
296-
}
297-
298288
pub(crate) fn collect_set(self, db: &dyn Db) -> (FxHashSet<File>, Vec<IOErrorDiagnostic>) {
299-
let (paths, diagnostics) = self.walk_paths();
300-
301-
let mut files = FxHashSet::with_capacity_and_hasher(paths.len(), FxBuildHasher);
302-
303-
for path in paths {
304-
if let Ok(file) = system_path_to_file(db, &path) {
305-
files.insert(file);
306-
}
307-
}
308-
309-
(files, diagnostics)
289+
let (files, diagnostics) = self.collect_vec(db);
290+
(files.into_iter().collect(), diagnostics)
310291
}
311292
}
312293

0 commit comments

Comments
 (0)