Skip to content

Commit

Permalink
fix: correct error count for cargo check --message-format json
Browse files Browse the repository at this point in the history
  • Loading branch information
yichi170 committed Sep 26, 2024
1 parent 01e1ab5 commit d9f9619
Showing 1 changed file with 51 additions and 33 deletions.
84 changes: 51 additions & 33 deletions src/cargo/core/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1742,6 +1742,33 @@ fn on_stderr_line_inner(
return Ok(true);
}

#[derive(serde::Deserialize)]
struct CompilerMessage {
rendered: String,
message: String,
level: String,
children: Vec<PartialDiagnostic>,
}

// A partial rustfix::diagnostics::Diagnostic. We deserialize only a
// subset of the fields because rustc's output can be extremely
// deeply nested JSON in pathological cases involving macro
// expansion. Rustfix's Diagnostic struct is recursive containing a
// field `children: Vec<Self>`, and it can cause deserialization to
// hit serde_json's default recursion limit, or overflow the stack
// if we turn that off. Cargo only cares about the 1 field listed
// here.
#[derive(serde::Deserialize)]
struct PartialDiagnostic {
spans: Vec<PartialDiagnosticSpan>,
}

// A partial rustfix::diagnostics::DiagnosticSpan.
#[derive(serde::Deserialize)]
struct PartialDiagnosticSpan {
suggestion_applicability: Option<Applicability>,
}

// Depending on what we're emitting from Cargo itself, we figure out what to
// do with this JSON message.
match options.format {
Expand All @@ -1755,33 +1782,6 @@ fn on_stderr_line_inner(
render_diagnostics: true,
..
} => {
#[derive(serde::Deserialize)]
struct CompilerMessage {
rendered: String,
message: String,
level: String,
children: Vec<PartialDiagnostic>,
}

// A partial rustfix::diagnostics::Diagnostic. We deserialize only a
// subset of the fields because rustc's output can be extremely
// deeply nested JSON in pathological cases involving macro
// expansion. Rustfix's Diagnostic struct is recursive containing a
// field `children: Vec<Self>`, and it can cause deserialization to
// hit serde_json's default recursion limit, or overflow the stack
// if we turn that off. Cargo only cares about the 1 field listed
// here.
#[derive(serde::Deserialize)]
struct PartialDiagnostic {
spans: Vec<PartialDiagnosticSpan>,
}

// A partial rustfix::diagnostics::DiagnosticSpan.
#[derive(serde::Deserialize)]
struct PartialDiagnosticSpan {
suggestion_applicability: Option<Applicability>,
}

if let Ok(mut msg) = serde_json::from_str::<CompilerMessage>(compiler_message.get()) {
if msg.message.starts_with("aborting due to")
|| msg.message.ends_with("warning emitted")
Expand Down Expand Up @@ -1865,12 +1865,30 @@ fn on_stderr_line_inner(
return Ok(true);
}

#[derive(serde::Deserialize)]
struct CompilerMessage {
level: String,
}
if let Ok(message) = serde_json::from_str::<CompilerMessage>(compiler_message.get()) {
count_diagnostic(&message.level, options);
if let Ok(msg) = serde_json::from_str::<CompilerMessage>(compiler_message.get()) {
if msg.message.starts_with("aborting due to")
|| msg.message.ends_with("warning emitted")
|| msg.message.ends_with("warnings emitted")
{
// Skip this line; we'll print our own summary at the end.
return Ok(true);
}
let rendered = msg.rendered;
if options.show_diagnostics {
let machine_applicable: bool = msg
.children
.iter()
.map(|child| {
child
.spans
.iter()
.filter_map(|span| span.suggestion_applicability)
.any(|app| app == Applicability::MachineApplicable)
})
.any(|b| b);
count_diagnostic(&msg.level, options);
state.emit_diag(msg.level, rendered, machine_applicable)?;
}
}

let msg = machine_message::FromCompiler {
Expand Down

0 comments on commit d9f9619

Please sign in to comment.