pub const DEFAULT_MARKERS: &[&str] = &[
"@generated",
"do not edit",
"automatically generated",
"auto-generated",
"autogenerated",
];
pub const DEFAULT_SCAN_LINES: usize = 10;
#[derive(Debug, Clone)]
pub struct GeneratedMarkers {
markers: Vec<String>,
scan_lines: usize,
}
impl Default for GeneratedMarkers {
fn default() -> Self {
let markers: Vec<String> = DEFAULT_MARKERS.iter().map(|m| (*m).to_string()).collect();
Self::new(&markers, DEFAULT_SCAN_LINES)
}
}
impl GeneratedMarkers {
#[must_use]
pub fn new(markers: &[String], scan_lines: usize) -> Self {
Self {
markers: markers.iter().map(|m| m.to_lowercase()).collect(),
scan_lines,
}
}
#[must_use]
pub fn with_additional(extra: &[String]) -> Self {
let mut markers: Vec<String> = DEFAULT_MARKERS.iter().map(|m| (*m).to_string()).collect();
markers.extend(extra.iter().cloned());
Self::new(&markers, DEFAULT_SCAN_LINES)
}
#[must_use]
pub fn is_generated(&self, head: &str) -> bool {
head.lines().take(self.scan_lines).any(|line| {
let line = line.to_lowercase();
self.markers.iter().any(|marker| line.contains(marker))
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_markers_match_the_banners_generators_write() {
let markers = GeneratedMarkers::default();
assert!(markers.is_generated("// This file is @generated by prost-build."));
assert!(markers.is_generated("// Code generated by protoc. DO NOT EDIT."));
assert!(markers.is_generated("/* automatically generated by rust-bindgen 0.72.1 */"));
assert!(
markers.is_generated("// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:")
);
assert!(
markers.is_generated("//! Generated by `cargo codegen grammar`, do not edit by hand.")
);
assert!(markers.is_generated("// --- Autogenerated from scripts/autogen.py ---"));
assert!(markers.is_generated("// auto-generated by: jiff-cli generate crc32"));
}
#[test]
fn hand_written_files_are_not_generated() {
let markers = GeneratedMarkers::default();
assert!(!markers.is_generated("//! A normal module.\nfn real() {}"));
}
#[test]
fn prose_about_generated_code_is_not_a_banner() {
let markers = GeneratedMarkers::default();
assert!(!markers.is_generated(
"//! Utilities used by macros and by the derive crate.\n\
//!\n\
//! These are defined here rather than in code generated by macros\n\
//! so that they can be compiled once.\n"
));
}
#[test]
fn markers_past_the_scan_window_are_ignored() {
let markers = GeneratedMarkers::new(&["@generated".to_string()], 2);
let head = "line1\nline2\n// @generated\n";
assert!(!markers.is_generated(head));
}
#[test]
fn additional_markers_extend_the_defaults() {
let markers = GeneratedMarkers::with_additional(&["AUTOGENERATED".to_string()]);
assert!(markers.is_generated("# AUTOGENERATED FILE\n"));
assert!(markers.is_generated("// @generated\n"));
}
}