|
1 | 1 | //! Basic operations useful for building a testsuite
|
2 | 2 |
|
3 | 3 | use crate::test_result::Errored;
|
4 |
| -use bstr::ByteSlice as _; |
5 | 4 | use color_eyre::eyre::Result;
|
6 | 5 | use crossbeam_channel::unbounded;
|
7 | 6 | use crossbeam_channel::Receiver;
|
8 | 7 | use crossbeam_channel::Sender;
|
| 8 | +use regex::bytes::RegexSet; |
9 | 9 | use std::num::NonZeroUsize;
|
10 | 10 | use std::path::Component;
|
11 | 11 | use std::path::Path;
|
12 | 12 | use std::path::Prefix;
|
13 | 13 | use std::process::Command;
|
14 | 14 | use std::process::Output;
|
| 15 | +use std::sync::OnceLock; |
15 | 16 | use std::thread;
|
16 | 17 |
|
17 | 18 | pub(crate) fn run_command(cmd: &mut Command) -> Result<Output, Errored> {
|
@@ -53,20 +54,28 @@ pub(crate) fn strip_path_prefix<'a>(
|
53 | 54 |
|
54 | 55 | impl CrateType {
|
55 | 56 | /// Heuristic:
|
56 |
| - /// * if the file contains `#[test]`, automatically pass `--cfg test`. |
57 |
| - /// * if the file does not contain `fn main()` or `#[start]`, automatically pass `--crate-type=lib`. |
58 |
| - /// This avoids having to spam `fn main() {}` in almost every test. |
| 57 | + /// * [`CrateType::ProcMacro`] if the file contains a [proc macro attribute] |
| 58 | + /// * [`CrateType::Test`] if the file contains `#[test]` |
| 59 | + /// * [`CrateType::Bin`] if the file contains `fn main()` or `#[start]` |
| 60 | + /// * otherwise [`CrateType::Lib`] |
| 61 | + /// |
| 62 | + /// [proc macro attribute]: https://doc.rust-lang.org/reference/procedural-macros.html |
59 | 63 | pub fn from_file_contents(file_contents: &[u8]) -> CrateType {
|
60 |
| - if file_contents.find(b"#[proc_macro").is_some() { |
61 |
| - CrateType::ProcMacro |
62 |
| - } else if file_contents.find(b"#[test]").is_some() { |
63 |
| - CrateType::Test |
64 |
| - } else if file_contents.find(b"fn main()").is_none() |
65 |
| - && file_contents.find(b"#[start]").is_none() |
66 |
| - { |
67 |
| - CrateType::Lib |
68 |
| - } else { |
69 |
| - CrateType::Bin |
| 64 | + static RE: OnceLock<RegexSet> = OnceLock::new(); |
| 65 | + let re = RE.get_or_init(|| { |
| 66 | + RegexSet::new([ |
| 67 | + r"#\[proc_macro(_derive|_attribute)?[\](]", |
| 68 | + r"#\[test\]", |
| 69 | + r"fn main()|#\[start\]", |
| 70 | + ]) |
| 71 | + .unwrap() |
| 72 | + }); |
| 73 | + |
| 74 | + match re.matches(file_contents).iter().next() { |
| 75 | + Some(0) => CrateType::ProcMacro, |
| 76 | + Some(1) => CrateType::Test, |
| 77 | + Some(2) => CrateType::Bin, |
| 78 | + _ => CrateType::Lib, |
70 | 79 | }
|
71 | 80 | }
|
72 | 81 | }
|
|
0 commit comments