Skip to content

Commit

Permalink
Support diagnostic error codes (#1268)
Browse files Browse the repository at this point in the history
fix #1178
  • Loading branch information
maciektr authored Apr 15, 2024
1 parent 5433c69 commit 3a25eb1
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 5 deletions.
16 changes: 14 additions & 2 deletions scarb/src/compiler/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,20 @@ pub fn build_compiler_config<'c>(
.strip_suffix('\n')
.unwrap_or(entry.message());
match entry.severity() {
Severity::Error => config.ui().error(msg),
Severity::Warning => config.ui().warn(msg),
Severity::Error => {
if let Some(code) = entry.error_code() {
config.ui().error_with_code(code.as_str(), msg)
} else {
config.ui().error(msg)
}
}
Severity::Warning => {
if let Some(code) = entry.error_code() {
config.ui().warn_with_code(code.as_str(), msg)
} else {
config.ui().warn(msg)
}
}
};
}
});
Expand Down
30 changes: 28 additions & 2 deletions scarb/tests/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,7 @@ fn warnings_allowed_by_default() {
.success()
.stdout_matches(indoc! {r#"
[..] Compiling [..] v1.0.0 ([..]Scarb.toml)
warn: Unused variable. Consider ignoring by prefixing with `_`.
warn[E0001]: Unused variable. Consider ignoring by prefixing with `_`.
--> [..]lib.cairo:2:9
let a = 41;
^
Expand Down Expand Up @@ -852,7 +852,7 @@ fn warnings_can_be_disallowed() {
.failure()
.stdout_matches(indoc! {r#"
[..] Compiling [..] v1.0.0 ([..]Scarb.toml)
warn: Unused variable. Consider ignoring by prefixing with `_`.
warn[E0001]: Unused variable. Consider ignoring by prefixing with `_`.
--> [..]lib.cairo:2:9
let a = 41;
^
Expand All @@ -861,6 +861,32 @@ fn warnings_can_be_disallowed() {
"#});
}

#[test]
fn error_codes_shown_in_json_output() {
let t = TempDir::new().unwrap();
ProjectBuilder::start()
.lib_cairo(indoc! {r#"
fn hello() -> felt252 {
let a = 41;
let b = 42;
b
}
"#})
.build(&t);

Scarb::quick_snapbox()
.arg("--json")
.arg("build")
.current_dir(&t)
.assert()
.success()
.stdout_matches(indoc! {r#"
{"status":"compiling","message":"[..] v1.0.0 ([..]Scarb.toml)"}
{"type":"warn","message":"Unused variable. Consider ignoring by prefixing with `_`./n --> [..]lib.cairo:2:9/n let a = 41;/n ^/n","code":"E0001"}
{"status":"finished","message":"release target(s) in [..]"}
"#});
}

#[test]
fn can_compile_no_core_package() {
let t = TempDir::new().unwrap();
Expand Down
23 changes: 22 additions & 1 deletion utils/scarb-ui/src/components/typed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ pub struct TypedMessage<'a> {
r#type: &'a str,
message: &'a str,

#[serde(skip_serializing_if = "Option::is_none")]
code: Option<&'a str>,

#[serde(skip)]
type_style: Option<&'a str>,
#[serde(skip)]
Expand All @@ -26,6 +29,7 @@ impl<'a> TypedMessage<'a> {
message,
type_style: Some(type_style),
skip_type_for_text: false,
code: None,
}
}

Expand All @@ -43,6 +47,19 @@ impl<'a> TypedMessage<'a> {
message,
type_style: None,
skip_type_for_text: true,
code: None,
}
}

/// Sometimes, a message may be associated with a short machine-readable descriptor.
/// For example, some compilers associate numerical *codes* with various kinds of errors
/// that can be produced.
/// The optional `code` field allows carrying this information.
/// This will be shown as suffix in text mode, and as a `code` field in structured mode.
pub fn with_code(self, code: &'a str) -> Self {
Self {
code: Some(code),
..self
}
}
}
Expand All @@ -57,7 +74,11 @@ impl<'a> Message for TypedMessage<'a> {
self.type_style
.map(Style::from_dotted_str)
.unwrap_or_default()
.apply_to(self.r#type),
.apply_to(format!(
"{}{}",
self.r#type,
self.code.map(|c| format!("[{c}]")).unwrap_or_default()
)),
self.message
)
}
Expand Down
12 changes: 12 additions & 0 deletions utils/scarb-ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,18 @@ impl Ui {
self.print(TypedMessage::styled("error", "red", message.as_ref()))
}

/// Print a warning to the user.
pub fn warn_with_code(&self, code: impl AsRef<str>, message: impl AsRef<str>) {
self.print(
TypedMessage::styled("warn", "yellow", message.as_ref()).with_code(code.as_ref()),
)
}

/// Print an error to the user.
pub fn error_with_code(&self, code: impl AsRef<str>, message: impl AsRef<str>) {
self.print(TypedMessage::styled("error", "red", message.as_ref()).with_code(code.as_ref()))
}

/// Nicely format an [`anyhow::Error`] for display to the user, and print it with [`Ui::error`].
pub fn anyhow(&self, error: &anyhow::Error) {
// NOTE: Some errors, particularly ones from `toml_edit` like to add trailing newlines.
Expand Down

0 comments on commit 3a25eb1

Please sign in to comment.