matchers.rs
116 lines
| 4.1 KiB
| application/rls-services+xml
|
RustLexer
Raphaël Gomès
|
r43742 | // matchers.rs | ||
// | ||||
// Copyright 2019 Raphaël Gomès <rgomes@octobus.net> | ||||
// | ||||
// This software may be used and distributed according to the terms of the | ||||
// GNU General Public License version 2 or any later version. | ||||
//! Structs and types for matching files and directories. | ||||
Raphaël Gomès
|
r44315 | use crate::utils::hg_path::HgPath; | ||
Raphaël Gomès
|
r43742 | use std::collections::HashSet; | ||
Raphaël Gomès
|
r44284 | pub enum VisitChildrenSet<'a> { | ||
Raphaël Gomès
|
r43742 | /// Don't visit anything | ||
Empty, | ||||
/// Only visit this directory | ||||
This, | ||||
/// Visit this directory and these subdirectories | ||||
/// TODO Should we implement a `NonEmptyHashSet`? | ||||
Raphaël Gomès
|
r44284 | Set(HashSet<&'a HgPath>), | ||
Raphaël Gomès
|
r43742 | /// Visit this directory and all subdirectories | ||
Recursive, | ||||
} | ||||
pub trait Matcher { | ||||
/// Explicitly listed files | ||||
Raphaël Gomès
|
r44284 | fn file_set(&self) -> Option<&HashSet<&HgPath>>; | ||
Raphaël Gomès
|
r43742 | /// Returns whether `filename` is in `file_set` | ||
Raphaël Gomès
|
r44009 | fn exact_match(&self, filename: impl AsRef<HgPath>) -> bool; | ||
Raphaël Gomès
|
r43742 | /// Returns whether `filename` is matched by this matcher | ||
Raphaël Gomès
|
r44009 | fn matches(&self, filename: impl AsRef<HgPath>) -> bool; | ||
Raphaël Gomès
|
r43742 | /// Decides whether a directory should be visited based on whether it | ||
/// has potential matches in it or one of its subdirectories, and | ||||
/// potentially lists which subdirectories of that directory should be | ||||
/// visited. This is based on the match's primary, included, and excluded | ||||
/// patterns. | ||||
/// | ||||
/// # Example | ||||
/// | ||||
/// Assume matchers `['path:foo/bar', 'rootfilesin:qux']`, we would | ||||
/// return the following values (assuming the implementation of | ||||
/// visit_children_set is capable of recognizing this; some implementations | ||||
/// are not). | ||||
/// | ||||
/// ```ignore | ||||
/// '' -> {'foo', 'qux'} | ||||
/// 'baz' -> set() | ||||
/// 'foo' -> {'bar'} | ||||
/// // Ideally this would be `Recursive`, but since the prefix nature of | ||||
/// // matchers is applied to the entire matcher, we have to downgrade this | ||||
/// // to `This` due to the (yet to be implemented in Rust) non-prefix | ||||
/// // `RootFilesIn'-kind matcher being mixed in. | ||||
/// 'foo/bar' -> 'this' | ||||
/// 'qux' -> 'this' | ||||
/// ``` | ||||
/// # Important | ||||
/// | ||||
/// Most matchers do not know if they're representing files or | ||||
/// directories. They see `['path:dir/f']` and don't know whether `f` is a | ||||
/// file or a directory, so `visit_children_set('dir')` for most matchers | ||||
/// will return `HashSet{ HgPath { "f" } }`, but if the matcher knows it's | ||||
/// a file (like the yet to be implemented in Rust `ExactMatcher` does), | ||||
/// it may return `VisitChildrenSet::This`. | ||||
/// Do not rely on the return being a `HashSet` indicating that there are | ||||
/// no files in this dir to investigate (or equivalently that if there are | ||||
/// files to investigate in 'dir' that it will always return | ||||
/// `VisitChildrenSet::This`). | ||||
fn visit_children_set( | ||||
&self, | ||||
Raphaël Gomès
|
r44009 | directory: impl AsRef<HgPath>, | ||
) -> VisitChildrenSet; | ||||
Raphaël Gomès
|
r43742 | /// Matcher will match everything and `files_set()` will be empty: | ||
/// optimization might be possible. | ||||
Raphaël Gomès
|
r44009 | fn matches_everything(&self) -> bool; | ||
Raphaël Gomès
|
r43742 | /// Matcher will match exactly the files in `files_set()`: optimization | ||
/// might be possible. | ||||
Raphaël Gomès
|
r44009 | fn is_exact(&self) -> bool; | ||
Raphaël Gomès
|
r43742 | } | ||
/// Matches everything. | ||||
Raphaël Gomès
|
r44286 | ///``` | ||
/// use hg::{ matchers::{Matcher, AlwaysMatcher}, utils::hg_path::HgPath }; | ||||
/// | ||||
/// let matcher = AlwaysMatcher; | ||||
/// | ||||
/// assert_eq!(true, matcher.matches(HgPath::new(b"whatever"))); | ||||
/// assert_eq!(true, matcher.matches(HgPath::new(b"b.txt"))); | ||||
/// assert_eq!(true, matcher.matches(HgPath::new(b"main.c"))); | ||||
/// assert_eq!(true, matcher.matches(HgPath::new(br"re:.*\.c$"))); | ||||
/// ``` | ||||
Raphaël Gomès
|
r43742 | #[derive(Debug)] | ||
pub struct AlwaysMatcher; | ||||
impl Matcher for AlwaysMatcher { | ||||
Raphaël Gomès
|
r44284 | fn file_set(&self) -> Option<&HashSet<&HgPath>> { | ||
None | ||||
Raphaël Gomès
|
r43742 | } | ||
Raphaël Gomès
|
r44009 | fn exact_match(&self, _filename: impl AsRef<HgPath>) -> bool { | ||
false | ||||
} | ||||
fn matches(&self, _filename: impl AsRef<HgPath>) -> bool { | ||||
true | ||||
} | ||||
Raphaël Gomès
|
r43742 | fn visit_children_set( | ||
&self, | ||||
_directory: impl AsRef<HgPath>, | ||||
) -> VisitChildrenSet { | ||||
VisitChildrenSet::Recursive | ||||
} | ||||
Raphaël Gomès
|
r44009 | fn matches_everything(&self) -> bool { | ||
true | ||||
} | ||||
fn is_exact(&self) -> bool { | ||||
false | ||||
} | ||||
Raphaël Gomès
|
r43742 | } | ||