mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 04:55:42 +09:00
116 lines
3.2 KiB
Rust
116 lines
3.2 KiB
Rust
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
use crate::common::collect_files;
|
|
use anyhow::{Context, Result};
|
|
use clap::Args;
|
|
use std::fs;
|
|
use std::path::{Path, PathBuf};
|
|
|
|
#[derive(Debug, Args, Clone)]
|
|
pub struct CleanSchemaGeneratedFilesArgs {
|
|
#[arg(long, default_value = "packages/schema/src/gen")]
|
|
root: PathBuf,
|
|
}
|
|
|
|
pub fn run_clean_generated_files(args: CleanSchemaGeneratedFilesArgs) -> Result<()> {
|
|
clean_generated_files(&args.root)
|
|
}
|
|
|
|
fn clean_generated_files(root: &Path) -> Result<()> {
|
|
for file in collect_files(root)?
|
|
.into_iter()
|
|
.filter(|path| path.extension().and_then(|value| value.to_str()) == Some("ts"))
|
|
{
|
|
let source = fs::read_to_string(&file)
|
|
.with_context(|| format!("Failed to read {}", file.display()))?;
|
|
let Some(import_index) = find_import_start(&source) else {
|
|
continue;
|
|
};
|
|
let content = format!(
|
|
"{}\n",
|
|
collapse_extra_blank_lines(source[import_index..].trim_end())
|
|
);
|
|
if content != source {
|
|
fs::write(&file, content)
|
|
.with_context(|| format!("Failed to write {}", file.display()))?;
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn find_import_start(source: &str) -> Option<usize> {
|
|
let mut offset = 0usize;
|
|
for line in source.split_inclusive('\n') {
|
|
if line.starts_with("import ") {
|
|
return Some(offset);
|
|
}
|
|
offset += line.len();
|
|
}
|
|
if source[offset..].starts_with("import ") {
|
|
return Some(offset);
|
|
}
|
|
None
|
|
}
|
|
|
|
fn collapse_extra_blank_lines(source: &str) -> String {
|
|
let mut output = String::with_capacity(source.len());
|
|
let mut consecutive_newlines = 0usize;
|
|
for ch in source.chars() {
|
|
if ch == '\n' {
|
|
consecutive_newlines += 1;
|
|
if consecutive_newlines <= 2 {
|
|
output.push(ch);
|
|
}
|
|
} else {
|
|
consecutive_newlines = 0;
|
|
output.push(ch);
|
|
}
|
|
}
|
|
output
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
fn write_file(path: &Path, contents: &str) {
|
|
if let Some(parent) = path.parent() {
|
|
fs::create_dir_all(parent).unwrap();
|
|
}
|
|
fs::write(path, contents).unwrap();
|
|
}
|
|
|
|
#[test]
|
|
fn find_import_start_only_matches_line_starts() {
|
|
assert_eq!(
|
|
find_import_start("// import nope\nimport {x} from 'x';\n"),
|
|
Some(15)
|
|
);
|
|
assert_eq!(find_import_start("const value = 'import nope';\n"), None);
|
|
}
|
|
|
|
#[test]
|
|
fn collapse_extra_blank_lines_keeps_at_most_one_blank_line() {
|
|
assert_eq!(collapse_extra_blank_lines("a\n\n\n\nb\n\nc"), "a\n\nb\n\nc");
|
|
}
|
|
|
|
#[test]
|
|
fn clean_generated_files_removes_prelude_and_compacts_blank_lines() {
|
|
let temp = tempfile::tempdir().unwrap();
|
|
let root = temp.path();
|
|
let file = root.join("generated.ts");
|
|
write_file(
|
|
&file,
|
|
"// header\n\n\nimport {x} from 'x';\n\n\n\nexport const y = x;\n\n",
|
|
);
|
|
write_file(&root.join("keep.txt"), "// header\n");
|
|
|
|
clean_generated_files(root).unwrap();
|
|
|
|
assert_eq!(
|
|
fs::read_to_string(file).unwrap(),
|
|
"import {x} from 'x';\n\nexport const y = x;\n"
|
|
);
|
|
}
|
|
}
|