1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
3
4use std::io::{BufWriter, Write};
5use std::path::Path;
6
7fn main() -> Result<(), Box<dyn std::error::Error>> {
8 let tests_file_path =
9 std::path::Path::new(&std::env::var_os("OUT_DIR").unwrap()).join("test_functions.rs");
10 let mut tests_file = BufWriter::new(std::fs::File::create(&tests_file_path)?);
11
12 let prefix = Path::new(env!("CARGO_MANIFEST_DIR")).join("../..").canonicalize()?;
13 for entry in walkdir::WalkDir::new(&prefix)
14 .follow_links(false)
15 .into_iter()
16 .filter_entry(|entry| entry.file_name() != "target")
17 {
18 let entry = entry?;
19 let path = entry.path();
20 if path.extension().map_or(true, |e| e != "md" && e != "mdx") {
21 continue;
22 }
23
24 let file = std::fs::read_to_string(path)?;
25 let file = file.replace('\r', ""); // Remove \r, because Windows.
26
27 const BEGIN_MARKER: &str = "\n```slint";
28 if !file.contains(BEGIN_MARKER) {
29 continue;
30 }
31
32 let stem = path
33 .strip_prefix(&prefix)?
34 .to_string_lossy()
35 .replace('-', "ˍ")
36 .replace(['/', '\\'], "Ⳇ")
37 .replace(['.'], "ᐧ")
38 .to_lowercase();
39
40 writeln!(tests_file, "\nmod {stem} {{")?;
41
42 let mut rest = file.as_str();
43 let mut line = 1;
44
45 while let Some(begin) = rest.find(BEGIN_MARKER) {
46 line += rest[..begin].bytes().filter(|&c| c == b'\n').count() + 1;
47 rest = rest[begin..].strip_prefix(BEGIN_MARKER).unwrap();
48
49 // Permit `slint,no-preview` and `slint,no-auto-preview` but skip `slint,ignore` and others.
50 rest = match rest.split_once('\n') {
51 Some((",ignore", _)) => continue,
52 Some((x, _)) if x.contains("no-test") => continue,
53 Some((_, rest)) => rest,
54 _ => continue,
55 };
56
57 let end = rest.find("\n```\n").ok_or_else(|| {
58 format!("Could not find the end of a code snippet in {}", path.display())
59 })?;
60 let snippet = &rest[..end];
61
62 if snippet.starts_with("{{#include") {
63 // Skip non literal slint text
64 continue;
65 }
66
67 rest = &rest[end..];
68
69 write!(
70 tests_file,
71 r##"
72 #[test]
73 fn line_{}() {{
74 crate::do_test("{}", "{}").unwrap();
75 }}
76
77 "##,
78 line,
79 snippet.escape_default(),
80 path.to_string_lossy().escape_default()
81 )?;
82
83 line += snippet.bytes().filter(|&c| c == b'\n').count() + 1;
84 }
85 writeln!(tests_file, "}}")?;
86 println!("cargo:rerun-if-changed={}", path.display());
87 }
88
89 println!("cargo:rustc-env=TEST_FUNCTIONS={}", tests_file_path.to_string_lossy());
90 println!("cargo:rustc-env=SLINT_ENABLE_EXPERIMENTAL_FEATURES=1");
91
92 Ok(())
93}
94