tokei/build.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

167 lines
4.9 KiB
Rust
Raw Permalink Normal View History

extern crate ignore;
extern crate serde_json;
extern crate json5;
use std::ffi::OsStr;
use std::fs;
2018-05-12 09:54:48 +00:00
use std::path::Path;
2019-10-30 19:31:24 +00:00
use std::{cmp, env, error};
2018-05-12 09:54:48 +00:00
use ignore::Walk;
2019-10-30 19:31:24 +00:00
use serde_json::Value;
fn main() -> Result<(), Box<dyn error::Error>> {
2018-05-12 09:54:48 +00:00
let out_dir = env::var_os("OUT_DIR").expect("No OUT_DIR variable.");
generate_languages(&out_dir)?;
generate_tests(&out_dir)?;
Ok(())
}
2019-10-30 19:31:24 +00:00
fn generate_languages(out_dir: &OsStr) -> Result<(), Box<dyn error::Error>> {
2020-05-28 07:28:09 +00:00
let mut tera = tera::Tera::default();
let json_string: String = fs::read_to_string("languages.json")?.parse()?;
let mut json: Value = json5::from_str(&json_string)?;
2019-10-30 19:31:24 +00:00
for (_key, ref mut item) in json
.get_mut("languages")
.unwrap()
.as_object_mut()
.unwrap()
.iter_mut()
2018-01-26 13:17:55 +00:00
{
macro_rules! sort_prop {
($prop:expr) => {{
if let Some(ref mut prop) = item.get_mut($prop) {
prop.as_array_mut()
.unwrap()
.sort_unstable_by(compare_json_str_len)
}
2019-10-30 19:31:24 +00:00
}};
2018-01-26 13:17:55 +00:00
}
sort_prop!("quotes");
sort_prop!("verbatim_quotes");
2018-01-26 13:17:55 +00:00
sort_prop!("multi_line");
}
2020-05-28 07:28:09 +00:00
let output_path = Path::new(&out_dir).join("language_type.rs");
2020-06-03 09:35:28 +00:00
let rust_code = tera.render_str(
2020-06-18 18:54:08 +00:00
&std::fs::read_to_string("src/language/language_type.tera.rs")?,
2020-06-03 09:35:28 +00:00
&tera::Context::from_value(json)?,
)?;
2020-05-28 07:28:09 +00:00
std::fs::write(output_path, rust_code)?;
2018-05-12 09:54:48 +00:00
Ok(())
}
2018-05-12 09:54:48 +00:00
fn compare_json_str_len(a: &Value, b: &Value) -> cmp::Ordering {
2018-01-26 13:17:55 +00:00
let a = a.as_array().expect("a as array");
let b = b.as_array().expect("b as array");
let max_a_size = a.iter().map(|e| e.as_str().unwrap().len()).max().unwrap();
let max_b_size = b.iter().map(|e| e.as_str().unwrap().len()).max().unwrap();
max_b_size.cmp(&max_a_size)
}
fn generate_tests(out_dir: &OsStr) -> Result<(), Box<dyn error::Error>> {
2018-05-12 09:54:48 +00:00
// Length of string literal below by number of languages
const INITIAL_BUFFER_SIZE: usize = 989 * 130;
let mut string = String::with_capacity(INITIAL_BUFFER_SIZE);
generate_tests_batch("./tests/data", None, &mut string)?;
generate_tests_batch("./tests/embedding", Some("embedding"), &mut string)?;
Ok(fs::write(Path::new(&out_dir).join("tests.rs"), string)?)
}
fn generate_tests_batch(
src_dir: &str,
test_module: Option<&str>,
string: &mut String,
) -> Result<(), Box<dyn error::Error>> {
let walker = Walk::new(src_dir).filter(|p| match p {
2020-02-14 13:21:20 +00:00
Ok(ref p) => {
2019-10-30 19:31:24 +00:00
if let Ok(ref p) = p.metadata() {
p.is_file()
} else {
false
}
}
2019-10-30 19:31:24 +00:00
_ => false,
});
if let Some(test_module) = test_module {
string.push_str(&format!(
r####"
#[cfg(test)]
mod {0} {{
use super::*;
"####,
test_module
));
}
for path in walker {
2018-05-12 09:54:48 +00:00
let path = path?;
let path = path.path();
let root = std::path::PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
let name = path.file_stem().unwrap().to_str().unwrap().to_lowercase();
2020-06-21 16:59:17 +00:00
if name == "jupyter" {
continue;
}
2019-10-30 19:31:24 +00:00
string.push_str(&format!(
2020-06-21 19:17:01 +00:00
r####"
#[test]
fn {0}() {{
2020-06-21 19:17:01 +00:00
const _: &str = include_str!(r###"{2}"###);
let mut languages = Languages::new();
2019-01-10 09:53:24 +00:00
languages.get_statistics(&["{1}"], &[], &Config::default());
if languages.len() != 1 {{
panic!("wrong languages detected: expected just {0}, found {{:?}}",
languages.into_iter().collect::<Vec<_>>());
}}
let (name, language) = languages.into_iter().next().unwrap();
let mut language = language.summarise();
2018-05-12 09:35:23 +00:00
let contents = fs::read_to_string("{1}").unwrap();
println!("{{}} {1}", name);
assert_eq!(get_digit!(LINES, contents), language.lines());
println!("{{}} LINES MATCH", name);
assert_eq!(get_digit!(CODE, contents), language.code);
println!("{{}} CODE MATCH", name);
assert_eq!(get_digit!(COMMENTS, contents), language.comments);
println!("{{}} COMMENTS MATCH", name);
assert_eq!(get_digit!(BLANKS, contents), language.blanks);
println!("{{}} BLANKS MATCH", name);
2020-04-02 16:18:37 +00:00
let report = language.reports.pop().unwrap();
let stats = report.stats.summarise();
2020-04-02 16:18:37 +00:00
assert_eq!(language.lines(), stats.lines());
assert_eq!(language.code, stats.code);
assert_eq!(language.comments, stats.comments);
assert_eq!(language.blanks, stats.blanks);
}}
2020-06-21 19:17:01 +00:00
"####,
2019-10-30 19:31:24 +00:00
name,
path.to_string_lossy().replace('\\', "/"),
2020-06-21 18:39:51 +00:00
std::fs::canonicalize(root.join(path)).unwrap().display(),
2019-10-30 19:31:24 +00:00
));
}
if test_module.is_some() {
string.push_str("\n}");
}
Ok(())
}