feat: add file and location to error reports

This commit is contained in:
Romain Paquet 2025-11-05 20:23:17 +01:00
parent ff586ca2d8
commit efb8607569

View file

@ -67,7 +67,7 @@ impl TypeError {
match &self.kind { match &self.kind {
TypeErrorKind::InvalidBinaryOperator { operator, lhs, rhs } => { TypeErrorKind::InvalidBinaryOperator { operator, lhs, rhs } => {
Report::build(ReportKind::Error, 0u32, 0) Report::build(ReportKind::Error, lhs.span.source, lhs.span.start)
.with_message(format!( .with_message(format!(
"Invalid binary operation {} between {} and {}", "Invalid binary operation {} between {} and {}",
operator.op.to_string().fg(c0), operator.op.to_string().fg(c0),
@ -100,36 +100,46 @@ impl TypeError {
let span = function.body.value.as_ref().unwrap().span; let span = function.body.value.as_ref().unwrap().span;
let report = Report::build(ReportKind::Error, 0u32, 0) let func_return_type_text = function
.with_message("Function body does not match the signature") .return_type
.with_labels([ .as_ref()
Label::new(function.body.span.unwrap()) .unwrap_or(&Type::Unit)
.with_message("In this function's body") .to_string()
.with_color(c2), .fg(signature_color);
let mut report = Report::build(
ReportKind::Error,
span.source,
function.body.value.as_ref().unwrap().span.start,
)
.with_message("Function body does not match the signature")
.with_labels([
Label::new(function.body.span.unwrap())
.with_message("In this function's body")
.with_color(c2),
Label::new(span)
.with_message(format!(
"Returned expression has type {} but the function should return {}",
block_type.to_string().fg(block_color),
func_return_type_text,
))
.with_color(block_color),
]);
if let Some(span) = function.return_type_span {
report.add_label(
Label::new(span) Label::new(span)
.with_message(format!( .with_message(format!("The signature shows {}", func_return_type_text))
"Returned expression has type {} but the function should return {}", .with_color(signature_color),
block_type.to_string().fg(block_color), );
function }
.return_type
.as_ref()
.unwrap_or(&Type::Unit)
.to_string()
.fg(signature_color)
))
.with_color(block_color),
]);
let report = report.set_note("The last expression of a function's body is returned");
report.with_note("The last expression of a function's body is returned");
let report = if function.return_type.is_none() { if function.return_type.is_none() {
report.with_help(
"You may need to add the return type to the function's signature",
)
} else {
report report
}; .set_help("You may need to add the return type to the function's signature")
}
report.finish() report.finish()
} }
@ -146,37 +156,36 @@ impl TypeError {
let is_bare_return = return_expr.is_none(); let is_bare_return = return_expr.is_none();
let report = Report::build(ReportKind::Error, *return_stmt.span.source(), 0) let mut report = Report::build(
.with_message("Return type does not match the function's signature") ReportKind::Error,
.with_label( *return_stmt.span.source(),
Label::new(return_expr.as_ref().unwrap_or(return_stmt).span) return_stmt.span.start,
.with_color(c1) )
.with_message(if is_bare_return { .with_message("Return type does not match the function's signature")
format!("Bare return has type {}", Type::Unit.to_string().fg(c1)) .with_label(
} else { Label::new(return_expr.as_ref().unwrap_or(return_stmt).span)
format!( .with_color(c1)
"This expression has type {}", .with_message(if is_bare_return {
return_stmt.ty.to_string().fg(c1) format!("Bare return has type {}", Type::Unit.to_string().fg(c1))
) } else {
}), format!(
); "This expression has type {}",
return_stmt.ty.to_string().fg(c1)
)
}),
);
let report = if let Some(ret_ty_span) = function.return_type_span { if let Some(ret_ty_span) = function.return_type_span {
report.with_label(Label::new(ret_ty_span).with_color(c0).with_message(format!( report.add_label(Label::new(ret_ty_span).with_color(c0).with_message(format!(
"The signature shows {}", "The signature shows {}",
function.return_type.as_ref().unwrap().to_string().fg(c0) function.return_type.as_ref().unwrap().to_string().fg(c0)
))) )))
} else { }
report
};
let report = if function.return_type.is_none() { if function.return_type.is_none() {
report.with_help(
"You may need to add the return type to the function's signature",
)
} else {
report report
}; .set_help("You may need to add the return type to the function's signature")
}
report.finish() report.finish()
} }