Skip to content

Commit 6fd3701

Browse files
committed
test type checking
1 parent 3cc9f84 commit 6fd3701

File tree

5 files changed

+57
-55
lines changed

5 files changed

+57
-55
lines changed

src/error.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,13 @@ pub enum CompileError {
152152
help("This is an internal compiler error. Please report it as a bug")
153153
)]
154154
Codegen(#[from] CodegenErrorData),
155+
156+
#[error(transparent)]
157+
#[diagnostic(
158+
code(descend::missing_main_error),
159+
help("A main function is required as the entry point of your program")
160+
)]
161+
MissingMain(#[from] MissingMainErrorData),
155162
}
156163

157164
/// Data for FileIO errors with miette diagnostic support
@@ -221,6 +228,18 @@ pub struct CodegenErrorData {
221228
pub span: Option<SourceSpan>,
222229
}
223230

231+
/// Data for MissingMain errors with miette diagnostic support
232+
#[derive(Error, Diagnostic, Debug, Clone)]
233+
#[error("Missing main function")]
234+
#[diagnostic(
235+
code(descend::missing_main_error),
236+
help("A main function is required as the entry point of your program")
237+
)]
238+
pub struct MissingMainErrorData {
239+
pub message: String,
240+
pub help_text: Option<String>,
241+
}
242+
224243
impl CompileError {
225244
/// Attach source code to the error for beautiful display
226245
pub fn with_source_code(self, source: miette::NamedSource<String>) -> miette::Report {
@@ -486,12 +505,9 @@ impl From<crate::ty_check::error::TyError> for CompileError {
486505
}
487506
}
488507
TyError::MissingMain => {
489-
CompileError::TypeCheck(TypeCheckErrorData {
508+
CompileError::MissingMain(MissingMainErrorData {
490509
message: "Missing main function".to_string(),
491-
span: None,
492-
secondary_spans: vec![],
493510
help_text: Some("A main function is required as the entry point of your program.".to_string()),
494-
related: None,
495511
})
496512
}
497513
TyError::NatEvalError(nat_err, span) => {

src/main.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use clap::Parser;
22
use descend;
3-
use descend::error::CompileError;
3+
use miette::IntoDiagnostic;
44
use std::fs;
55
use std::path::PathBuf;
66

@@ -20,7 +20,7 @@ struct Args {
2020
print_ast: bool,
2121
}
2222

23-
fn main() -> Result<(), CompileError> {
23+
fn main() -> miette::Result<()> {
2424
miette::set_panic_hook();
2525

2626
let args = Args::parse();
@@ -40,11 +40,11 @@ fn main() -> Result<(), CompileError> {
4040
if print_ast {
4141
let ast_file = output_dir.join(format!("{}.ast", filename_stem));
4242
// Write result to file
43-
fs::write(&ast_file, ast_string)?;
43+
fs::write(&ast_file, ast_string).into_diagnostic()?;
4444
println!("AST file written successfully to: {}", ast_file.display());
4545
}
4646
// Write result to file
47-
fs::write(&code_file, code_string)?;
47+
fs::write(&code_file, code_string).into_diagnostic()?;
4848
println!("code file written successfully to: {}", code_file.display());
4949

5050
Ok(())

tests/error_examples.rs

Lines changed: 30 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,57 +2,36 @@
22
// instead of using the macro which is designed for successful compilation tests
33

44
use descend::error::CompileError;
5-
use std::io::ErrorKind;
65

76
#[test]
8-
fn test_fileio_error() {
7+
fn fileio_error() {
98
// Test compilation of a non-existent file which should fail with a FileIO error
10-
let err = descend::compile("examples/error-examples/nonexistent_file.desc")
11-
.err()
12-
.unwrap();
13-
14-
// Also test the full miette diagnostic output
15-
let miette_report = miette::Report::new(err.clone());
16-
17-
// Use the graphical handler to get fancy output
18-
let handler = miette::GraphicalReportHandler::new();
19-
let mut output = String::new();
20-
handler
21-
.render_report(&mut output, miette_report.as_ref())
22-
.unwrap();
23-
24-
insta::assert_snapshot!(output);
25-
26-
// Assert that compilation failed with a FileIO error
27-
match err {
28-
CompileError::FileIO(data) => {
29-
assert_eq!(
30-
data.file_path,
31-
"examples/error-examples/nonexistent_file.desc"
32-
);
33-
assert_eq!(data.io_error_kind, ErrorKind::NotFound);
34-
}
35-
_ => panic!("Expected FileIO error, got {:?}", err),
36-
}
9+
test_error_compilation(
10+
"examples/error-examples/nonexistent_file.desc",
11+
|err| matches!(err, CompileError::FileIO(_)),
12+
"FileIO",
13+
);
3714
}
3815

3916
#[test]
40-
fn test_missing_main_error() {
41-
// Test the missing main error directly by calling the type checker
42-
use descend::parser::SourceCode;
43-
use descend::ty_check::error::TyError;
44-
45-
// Parse the file first
46-
let source = SourceCode::from_file("examples/error-examples/missing_main.desc").unwrap();
47-
let mut compil_unit = descend::parser::parse(&source).unwrap();
17+
fn missing_main_error() {
18+
// Test compilation of a file without a main function which should fail with a MissingMain error
19+
test_error_compilation(
20+
"examples/error-examples/missing_main.desc",
21+
|err| matches!(err, CompileError::MissingMain(_)),
22+
"MissingMain",
23+
);
24+
}
4825

49-
// Call type checker directly to get the actual MissingMain error
50-
let result = descend::ty_check::ty_check(&mut compil_unit);
51-
assert!(result.is_err()); // Should fail with MissingMain error
26+
fn test_error_compilation<F>(file_path: &str, error_checker: F, error_name: &str)
27+
where
28+
F: FnOnce(&CompileError) -> bool,
29+
{
30+
// Test compilation of a file which should fail with the expected error
31+
let err = descend::compile(file_path).err().unwrap();
5232

53-
// Test the actual MissingMain error diagnostic
54-
let missing_main_error = TyError::MissingMain;
55-
let miette_report = miette::Report::new(missing_main_error);
33+
// Also test the full miette diagnostic output
34+
let miette_report = miette::Report::new(err.clone());
5635

5736
// Use the graphical handler to get fancy output
5837
let handler = miette::GraphicalReportHandler::new();
@@ -61,5 +40,12 @@ fn test_missing_main_error() {
6140
.render_report(&mut output, miette_report.as_ref())
6241
.unwrap();
6342

64-
insta::assert_snapshot!(output);
43+
insta::assert_snapshot!(error_name, output);
44+
45+
assert!(
46+
error_checker(&err),
47+
"Expected {} error, got {:?}",
48+
error_name,
49+
err
50+
);
6551
}

tests/snapshots/error_examples__missing_main_error.snap renamed to tests/snapshots/error_examples__MissingMain.snap

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
source: tests/error_examples.rs
33
expression: output
44
---
5-
[31mdescend::ty_check::missing_main[0m
5+
[31mdescend::missing_main_error[0m
66

7-
[31m×[0m missing main function
8-
[36m help: [0mA main function is required as the entry point of your program.
7+
[31m×[0m Missing main function
8+
[36m help: [0mA main function is required as the entry point of your program

0 commit comments

Comments
 (0)