/
skeptic.rs
119 lines (94 loc) · 3.3 KB
/
skeptic.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#[cfg(feature = "logging")]
#[macro_use]
extern crate log;
#[cfg(feature = "logging")]
extern crate env_logger;
extern crate skeptic;
#[cfg(not(feature = "logging"))]
#[macro_use]
mod log_disabled {
include!("../src/log_disabled.rs");
}
fn main() {
println!("INFO: Run with `RUST_LOG=build_script_build=trace` for debug information.");
#[cfg(feature = "logging")]
env_logger::init();
let mut files = generate_doc_tpl_tests().unwrap();
files.push("README.md".to_string());
let files_ref: Vec<&str> = files.iter().map(|x| x.as_str()).collect();
skeptic::generate_doc_tests(files_ref.as_slice());
}
const DOC_TPL_HEADER: &'static str = r###"
//////////////////////////////////////////////////////////////////
// START of Header
// NOTE:
// - This file is auto-generated by the `build.rs` script.
// - The following skeptic-template is a Rust format specifier,
// so braces are treated specially, and need to be escaped
// with double-braces.
// See: https://github.com/brson/rust-skeptic#skeptic-templates
```rust,skeptic-template
#[macro_use]
extern crate derive_builder;
#[derive(Builder)]
struct Foo {{
#[allow(dead_code)]
default: bool,
}}
fn main() {{
{}
}}
```
// END of Header
//////////////////////////////////////////////////////////////////
"###;
use std::error::Error;
use std::path::PathBuf;
use std::env;
use std::fs::{File, DirBuilder};
use std::ffi::OsStr;
use std::io::{Write, Read};
const DOC_TPL_DIR: &'static str = "src/doc_tpl/";
const DOC_TPL_OUT_DIR: &'static str = "doc_tpl/";
fn generate_doc_tpl_tests() -> Result<Vec<String>, Box<dyn Error>> {
trace!("Generating doc template tests");
let root_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR")?);
let mut tpl_dir = root_dir;
tpl_dir.push(DOC_TPL_DIR);
let mut out_dir = PathBuf::from(env::var("OUT_DIR")?);
out_dir.push(DOC_TPL_OUT_DIR);
if !out_dir.is_dir() {
trace!("Create out dir {:?}", out_dir);
DirBuilder::new().create(&out_dir)?;
}
let docs = tpl_dir.read_dir().expect(&format!("Could not open {}", tpl_dir.display()));
let mut files = Vec::<String>::new();
for doc in docs {
let path: PathBuf = doc?.path();
let filename = match path.file_name() {
Some(filename) if path.extension() == Some(&OsStr::new("md")) => filename,
_ => {
trace!("Skipping dir entry {:?}", path.display());
continue;
}
};
trace!("Create tests for {:?}", path.display());
let mut reader = File::open(&path)?;
println!("cargo:rerun-if-changed={}", path.display());
let mut out_file = out_dir.clone();
out_file.push(filename);
trace!("Will write into {:?}", out_file.display());
let mut out = File::create(&out_file)?;
out.write_all(DOC_TPL_HEADER.as_bytes())?;
let mut tpl = String::new();
reader.read_to_string(&mut tpl)?;
let tpl = tpl.replace("{struct_name}", "Foo")
.replace("{builder_name}", "FooBuilder")
.replace("{field_name}", "default");
out.write_all(tpl.as_ref())?;
trace!("{:?}",
&[&out_file.to_str().expect("Path must not be empty")]);
files.push(out_file.to_str().expect("Path must not be empty").to_string());
}
Ok(files)
}