[red-knot] Watch search paths (#12407)

This commit is contained in:
Micha Reiser 2024-07-24 09:38:50 +02:00 committed by GitHub
parent 8659f2f4ea
commit eac965ecaf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 409 additions and 37 deletions

View file

@ -65,7 +65,7 @@ impl std::fmt::Debug for TargetVersion {
}
/// Configures the search paths for module resolution.
#[derive(Eq, PartialEq, Debug)]
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct SearchPathSettings {
/// List of user-provided paths that should take first priority in the module resolution.
/// Examples in other type checkers are mypy's MYPYPATH environment variable,

View file

@ -9,7 +9,9 @@ use walk_directory::WalkDirectoryBuilder;
use crate::file_revision::FileRevision;
pub use self::path::{SystemPath, SystemPathBuf};
pub use self::path::{
deduplicate_nested_paths, DeduplicatedNestedPathsIter, SystemPath, SystemPathBuf,
};
mod memory_fs;
#[cfg(feature = "os")]

View file

@ -563,3 +563,60 @@ impl ruff_cache::CacheKey for SystemPathBuf {
self.as_path().cache_key(hasher);
}
}
/// Deduplicates identical paths and removes nested paths.
///
/// # Examples
/// ```rust
/// use ruff_db::system::{SystemPath, deduplicate_nested_paths};///
///
/// let paths = vec![SystemPath::new("/a/b/c"), SystemPath::new("/a/b"), SystemPath::new("/a/beta"), SystemPath::new("/a/b/c")];
/// assert_eq!(deduplicate_nested_paths(paths).collect::<Vec<_>>(), &[SystemPath::new("/a/b"), SystemPath::new("/a/beta")]);
/// ```
pub fn deduplicate_nested_paths<'a, I>(paths: I) -> DeduplicatedNestedPathsIter<'a>
where
I: IntoIterator<Item = &'a SystemPath>,
{
DeduplicatedNestedPathsIter::new(paths)
}
pub struct DeduplicatedNestedPathsIter<'a> {
inner: std::vec::IntoIter<&'a SystemPath>,
next: Option<&'a SystemPath>,
}
impl<'a> DeduplicatedNestedPathsIter<'a> {
fn new<I>(paths: I) -> Self
where
I: IntoIterator<Item = &'a SystemPath>,
{
let mut paths = paths.into_iter().collect::<Vec<_>>();
// Sort the path to ensure that e.g. `/a/b/c`, comes right after `/a/b`.
paths.sort_unstable();
let mut iter = paths.into_iter();
Self {
next: iter.next(),
inner: iter,
}
}
}
impl<'a> Iterator for DeduplicatedNestedPathsIter<'a> {
type Item = &'a SystemPath;
fn next(&mut self) -> Option<Self::Item> {
let current = self.next.take()?;
for next in self.inner.by_ref() {
// Skip all paths that have the same prefix as the current path
if !next.starts_with(current) {
self.next = Some(next);
break;
}
}
Some(current)
}
}