litcheck_lit/config/
mod.rs1mod expr;
2mod features;
3pub(crate) mod substitutions;
4
5pub use self::expr::*;
6pub use self::features::FeatureSet;
7pub use self::substitutions::{
8 InvalidSubstitutionPatternError, ScopedSubstitutionSet, SubstitutionSet,
9};
10
11use std::{fmt, path::PathBuf, sync::Arc};
12
13use clap::Args;
14use litcheck::diagnostics::{DefaultSourceManager, SourceManagerSync};
15use regex::Regex;
16
17pub type Variable = litcheck::variables::Variable<String>;
18
19pub struct Config {
20 pub options: Options,
21 pub source_manager: Arc<dyn SourceManagerSync>,
22}
23
24impl Config {
25 pub fn new(tests: Vec<String>) -> Self {
26 Self {
27 options: Options {
28 tests,
29 workers: None,
30 params: vec![],
31 quiet: false,
32 verbose: false,
33 all: false,
34 no_execute: false,
35 search_paths: vec![],
36 timeout: None,
37 filter: None,
38 filter_out: None,
39 target: None,
40 },
41 source_manager: Arc::from(DefaultSourceManager::default()),
42 }
43 }
44
45 #[inline(always)]
46 pub fn source_manager(&self) -> &dyn SourceManagerSync {
47 &self.source_manager
48 }
49
50 pub fn is_selected(&self, name: &str) -> bool {
52 let is_selected = self
53 .options
54 .filter
55 .as_ref()
56 .map(|filter| filter.is_match(name))
57 .unwrap_or(true);
58 let is_excluded = self
59 .options
60 .filter_out
61 .as_ref()
62 .map(|filter_out| filter_out.is_match(name))
63 .unwrap_or(false);
64 is_selected && !is_excluded
65 }
66
67 pub fn host(&self) -> target_lexicon::Triple {
68 target_lexicon::Triple::host()
69 }
70
71 pub fn target(&self) -> target_lexicon::Triple {
72 self.options
73 .target
74 .clone()
75 .unwrap_or_else(target_lexicon::Triple::host)
76 }
77}
78
79impl Default for Config {
80 #[inline]
81 fn default() -> Self {
82 Self::new(vec![])
83 }
84}
85
86impl fmt::Debug for Config {
87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88 fmt::Debug::fmt(&self.options, f)
89 }
90}
91#[derive(Debug, Args)]
92pub struct Options {
93 #[arg(value_name = "TESTS", required(true), trailing_var_arg(true))]
95 pub tests: Vec<String>,
96 #[arg(long, short = 'j', value_name = "N")]
100 pub workers: Option<usize>,
101 #[arg(long = "param", short = 'D', value_name = "NAME=[VALUE]")]
103 pub params: Vec<Variable>,
104 #[arg(long, short = 'q', default_value_t = false, help_heading = "Output")]
106 pub quiet: bool,
107 #[arg(long, short = 'v', default_value_t = false, help_heading = "Output")]
112 pub verbose: bool,
113 #[arg(
115 long = "show-all",
116 short = 'a',
117 default_value_t = false,
118 help_heading = "Output"
119 )]
120 pub all: bool,
121 #[arg(
126 long = "no-execute",
127 default_value_t = false,
128 help_heading = "Execution Options"
129 )]
130 pub no_execute: bool,
131 #[arg(
133 long = "path",
134 value_name = "PATH",
135 value_parser(canonical_path_parser()),
136 help_heading = "Execution Options"
137 )]
138 pub search_paths: Vec<PathBuf>,
139 #[arg(
143 long,
144 value_name = "N",
145 default_value = "0",
146 help_heading = "Execution Options"
147 )]
148 pub timeout: Option<u64>,
149 #[arg(long, env = "LIT_FILTER", help_heading = "Selection Options")]
151 pub filter: Option<Regex>,
152 #[arg(long, env = "LIT_FILTER_OUT", help_heading = "Selection Options")]
154 pub filter_out: Option<Regex>,
155 #[arg(
161 long,
162 value_parser(target_triple_parser()),
163 value_name = "TRIPLE",
164 help_heading = "Selection Options"
165 )]
166 pub target: Option<target_lexicon::Triple>,
167}
168
169fn target_triple_parser() -> clap::builder::ValueParser {
170 use clap::{builder::ValueParser, error::ErrorKind, Error};
171 ValueParser::from(|s: &str| -> Result<target_lexicon::Triple, clap::Error> {
172 s.parse::<target_lexicon::Triple>().map_err(|err| {
173 Error::raw(
174 ErrorKind::ValueValidation,
175 format!("invalid target triple '{s}': {err}"),
176 )
177 })
178 })
179}
180
181fn canonical_path_parser() -> clap::builder::ValueParser {
182 use clap::{builder::ValueParser, error::ErrorKind, Error};
183 ValueParser::from(|s: &str| -> Result<PathBuf, clap::Error> {
184 let path = std::path::Path::new(s);
185 path.canonicalize().map_err(|err| {
186 Error::raw(
187 ErrorKind::ValueValidation,
188 format!("invalid path '{s}': {err}"),
189 )
190 })
191 })
192}