150 lines
4.6 KiB
Rust
150 lines
4.6 KiB
Rust
use dever::compiler::format;
|
|
use dever::syntax::source::Source;
|
|
use std::path::PathBuf;
|
|
|
|
#[test]
|
|
fn format_keeps_literals_comments_groups_and_field_order() {
|
|
let text = "# leading\nmain( ) (answer: Int) {\n answer=(1+2)*3 # same line\n}\n";
|
|
let source = Source::new(0, "case.dever", text.into());
|
|
let output = format::format(&source).unwrap();
|
|
assert_eq!(
|
|
output,
|
|
"# leading\nmain() (answer: Int) {\n answer = (1 + 2) * 3 # same line\n}\n"
|
|
);
|
|
assert_eq!(
|
|
format::format(&Source::new(0, "case.dever", output.clone())).unwrap(),
|
|
output
|
|
);
|
|
let literals = Source::new(
|
|
0,
|
|
"case.dever",
|
|
"main() (answer: Text) { answer=\"# \\u{41} \\\"\" }\n".into(),
|
|
);
|
|
assert!(
|
|
format::format(&literals)
|
|
.unwrap()
|
|
.contains("\"# \\u{41} \\\"\"")
|
|
);
|
|
let fields = Source::new(
|
|
0,
|
|
"case.dever",
|
|
"main() (answer: Item) { answer=Item { second=2, first=1 } }\n".into(),
|
|
);
|
|
assert!(
|
|
format::format(&fields)
|
|
.unwrap()
|
|
.contains("second = 2, first = 1")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn format_preserves_crlf() {
|
|
let text = "main( ) (answer: Int) {\r\n answer=1\r\n}\r\n";
|
|
let output = format::format(&Source::new(0, "case.dever", text.into())).unwrap();
|
|
assert_eq!(
|
|
output,
|
|
text.replace("main( )", "main()")
|
|
.replace(" answer=1", " answer = 1")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn format_preserves_local_type_annotations() {
|
|
let source = Source::new(
|
|
0,
|
|
"case.dever",
|
|
"main() () { value:List<Int?>=[null,1] }".into(),
|
|
);
|
|
let formatted = format::format(&source).unwrap();
|
|
assert!(
|
|
formatted.contains("value: List<Int?> = [null, 1]"),
|
|
"{formatted}"
|
|
);
|
|
assert_eq!(
|
|
format::format(&Source::new(0, "case.dever", formatted.clone())).unwrap(),
|
|
formatted
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn format_preserves_text_policy_and_camel_functions() {
|
|
let input = "type Category { name: Text(1,80)\ncode: Text lower unique\nbody: Text raw\nnote: Text? upper }\nreadName(input_value: Text) (output_value: Text) { output_value = input_value }";
|
|
let output = format::format(&Source::new(0, "model.dever", input.into())).unwrap();
|
|
for preserved in [
|
|
"code: Text lower unique",
|
|
"body: Text raw",
|
|
"note: Text? upper",
|
|
"readName(input_value: Text)",
|
|
] {
|
|
assert!(output.contains(preserved), "{output}");
|
|
}
|
|
assert_eq!(
|
|
format::format(&Source::new(0, "model.dever", output.clone())).unwrap(),
|
|
output
|
|
);
|
|
}
|
|
|
|
struct Directory(PathBuf);
|
|
|
|
impl Directory {
|
|
fn new() -> Self {
|
|
let path = std::env::temp_dir().join(format!(
|
|
"dever-format-{}-{}",
|
|
std::process::id(),
|
|
std::time::SystemTime::now()
|
|
.duration_since(std::time::UNIX_EPOCH)
|
|
.unwrap()
|
|
.as_nanos()
|
|
));
|
|
std::fs::create_dir(&path).unwrap();
|
|
Self(path)
|
|
}
|
|
}
|
|
|
|
impl Drop for Directory {
|
|
fn drop(&mut self) {
|
|
let _ = std::fs::remove_dir_all(&self.0);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn project_prepares_module_and_tests_before_any_rewrite() {
|
|
let directory = Directory::new();
|
|
std::fs::create_dir(directory.0.join("module")).unwrap();
|
|
std::fs::create_dir(directory.0.join("test")).unwrap();
|
|
let module = directory.0.join("module/main.dever");
|
|
let test = directory.0.join("test/main.dever");
|
|
let input = "main( ) () {}\n";
|
|
std::fs::write(&module, input).unwrap();
|
|
std::fs::write(&test, "main( {").unwrap();
|
|
assert!(format::project(&directory.0, false).is_err());
|
|
assert_eq!(std::fs::read_to_string(&module).unwrap(), input);
|
|
std::fs::write(&test, input).unwrap();
|
|
let report = format::project(&directory.0, true).unwrap();
|
|
assert_eq!(report.checked, 2);
|
|
assert_eq!(report.changed.len(), 2);
|
|
assert_eq!(std::fs::read_to_string(&module).unwrap(), input);
|
|
format::project(&directory.0, false).unwrap();
|
|
assert!(
|
|
format::project(&directory.0, true)
|
|
.unwrap()
|
|
.changed
|
|
.is_empty()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[cfg(unix)]
|
|
fn project_rejects_links_without_touching_their_target() {
|
|
let directory = Directory::new();
|
|
let target = directory.0.join("actual.dever");
|
|
std::fs::write(&target, "main( ) () {}\n").unwrap();
|
|
std::os::unix::fs::symlink(&target, directory.0.join("link.dever")).unwrap();
|
|
assert!(
|
|
format::project(&directory.0, false)
|
|
.unwrap_err()
|
|
.contains("links")
|
|
);
|
|
assert_eq!(std::fs::read_to_string(target).unwrap(), "main( ) () {}\n");
|
|
}
|