Add tests for label-processing diagnostics

This commit is contained in:
2025-07-05 22:53:02 -07:00
parent 2e5999ef1e
commit eee57848e0
6 changed files with 116 additions and 13 deletions
+13 -1
View File
@@ -77,7 +77,19 @@ impl<'a> Context<'a> {
pub fn into_messages(self) -> Vec<CompileMessage> { pub fn into_messages(self) -> Vec<CompileMessage> {
match self { match self {
Context::Base(refcell) => refcell.into_inner(), Context::Base(refcell) => {
let mut messages = refcell.into_inner();
messages.sort_by_key(|msg| {
let loc = &msg.location;
(
loc.file_path.as_ref().map(|x| x.clone()),
loc.board,
loc.stat,
loc.span.as_ref().map(|s| s.start),
)
});
messages
}
_ => panic!("into_messages() may only be called on the base context"), _ => panic!("into_messages() may only be called on the base context"),
} }
} }
+36 -10
View File
@@ -8,7 +8,9 @@ use super::{
sanitize::Registry, sanitize::Registry,
}; };
pub fn process_labels(board: &mut Board, ctx: &Context) { pub fn process_labels(board: &Board, ctx: &Context) -> Board {
let mut board = board.clone();
// Parse stats into chunks // Parse stats into chunks
let mut stats: Vec<ParsedStat> = board let mut stats: Vec<ParsedStat> = board
.stats .stats
@@ -40,6 +42,8 @@ pub fn process_labels(board: &mut Board, ctx: &Context) {
.collect(); .collect();
old_stat.code = new_code; old_stat.code = new_code;
} }
board
} }
/// Resolve ".local" labels to "name.local" form. /// Resolve ".local" labels to "name.local" form.
@@ -218,7 +222,7 @@ mod test {
use crate::{ use crate::{
error::Context, error::Context,
world::{Board, Stat}, world::{Board, Stat, World},
}; };
use super::process_labels; use super::process_labels;
@@ -251,6 +255,12 @@ mod test {
board board
} }
fn world_from_text(path: &str) -> World {
let mut world = World::default();
world.boards.push(board_from_text(path));
world
}
fn board_to_text(board: Board) -> String { fn board_to_text(board: Board) -> String {
let codes: Vec<_> = board.stats.into_iter().map(|stat| stat.code).collect(); let codes: Vec<_> = board.stats.into_iter().map(|stat| stat.code).collect();
codes.join("---\n") codes.join("---\n")
@@ -258,29 +268,45 @@ mod test {
#[test] #[test]
fn test_label_sanitization() { fn test_label_sanitization() {
let mut board = board_from_text("tests/labels/sanitize.txt"); let board = board_from_text("tests/labels/sanitize.txt");
let _ = process_labels(&mut board, &Context::new()); let board = process_labels(&board, &Context::new());
assert_snapshot!(board_to_text(board)); assert_snapshot!(board_to_text(board));
} }
#[test] #[test]
fn test_anonymous_labels() { fn test_anonymous_labels() {
let mut board = board_from_text("tests/labels/anonymous.txt"); let board = board_from_text("tests/labels/anonymous.txt");
let _ = process_labels(&mut board, &Context::new()); let board = process_labels(&board, &Context::new());
assert_snapshot!(board_to_text(board)); assert_snapshot!(board_to_text(board));
} }
#[test] #[test]
fn test_local_labels() { fn test_local_labels() {
let mut board = board_from_text("tests/labels/local.txt"); let board = board_from_text("tests/labels/local.txt");
let _ = process_labels(&mut board, &Context::new()); let board = process_labels(&board, &Context::new());
assert_snapshot!(board_to_text(board)); assert_snapshot!(board_to_text(board));
} }
#[test] #[test]
fn test_namespaces() { fn test_namespaces() {
let mut board = board_from_text("tests/labels/namespaces.txt"); let board = board_from_text("tests/labels/namespaces.txt");
let _ = process_labels(&mut board, &Context::new()); let board = process_labels(&board, &Context::new());
assert_snapshot!(board_to_text(board)); assert_snapshot!(board_to_text(board));
} }
#[test]
fn test_diagnostics() {
let world = world_from_text("tests/labels/diagnostics.txt");
let base_ctx = Context::new();
process_labels(
&world.boards[0],
&base_ctx.with_file_path("test.zzt").with_board(0),
);
let messages: Vec<String> = base_ctx
.into_messages()
.iter()
.map(|x| x.rich_format(&world))
.collect();
assert_snapshot!(messages.join("\n\n"));
}
} }
@@ -0,0 +1,46 @@
---
source: src/labels/process.rs
expression: "messages.join(\"\\n\\n\")"
---
warning: trailing characters at end of line
=> test.zzt -> Title screen -> @Trailing (1,1) -> line 2:5
|
1 | @Trailing
2 | #end trailing text
| ^^^^^^^^^^^^^^
error: backward reference needs an anonymous label
=> test.zzt -> Title screen -> @Invalid anon (1,1) -> line 2:7
|
1 | @Invalid anon
2 | #send @b
| ^^
3 | :@
4 | #send @f
|
error: forward reference needs an anonymous label
=> test.zzt -> Title screen -> @Invalid anon (1,1) -> line 4:7
|
1 | @Invalid anon
2 | #send @b
3 | :@
4 | #send @f
| ^^
error: forward reference needs an anonymous label
=> test.zzt -> Title screen -> @Errors in sorted order (1,1) -> line 2:7
|
1 | @Errors in sorted order
2 | #send @f
| ^^
3 | #send @b
|
error: backward reference needs an anonymous label
=> test.zzt -> Title screen -> @Errors in sorted order (1,1) -> line 3:7
|
1 | @Errors in sorted order
2 | #send @f
3 | #send @b
| ^^
+2 -2
View File
@@ -40,9 +40,9 @@ fn main() -> Result<(), Box<dyn Error>> {
// Resolve labels to proper ZZT-OOP // Resolve labels to proper ZZT-OOP
let base_ctx = ErrContext::new(); let base_ctx = ErrContext::new();
let ctx = base_ctx.with_file_path(&world_filename); let ctx = base_ctx.with_file_path(&world_filename);
for (i, mut board) in world.boards.iter_mut().enumerate() { for (i, board) in world.boards.iter_mut().enumerate() {
let ctx = ctx.with_board(i); let ctx = ctx.with_board(i);
process_labels(&mut board, &ctx); *board = process_labels(&board, &ctx);
} }
// Print diagnostics // Print diagnostics
+3
View File
@@ -70,6 +70,7 @@ impl Error for LoadError {
} }
} }
#[derive(Default)]
pub struct World { pub struct World {
pub ammo: i16, pub ammo: i16,
pub gems: i16, pub gems: i16,
@@ -88,6 +89,7 @@ pub struct World {
pub boards: Vec<Board>, pub boards: Vec<Board>,
} }
#[derive(Clone)]
pub struct Board { pub struct Board {
pub name: String, pub name: String,
pub terrain: Vec<[u8; 2]>, pub terrain: Vec<[u8; 2]>,
@@ -105,6 +107,7 @@ pub struct Board {
pub stats: Vec<Stat>, pub stats: Vec<Stat>,
} }
#[derive(Clone)]
pub struct Stat { pub struct Stat {
pub x: u8, pub x: u8,
pub y: u8, pub y: u8,
+16
View File
@@ -0,0 +1,16 @@
@Trailing
#end trailing text
---
@Valid anon
#send @f
:@
#send @b
---
@Invalid anon
#send @b
:@
#send @f
---
@Errors in sorted order
#send @f
#send @b