Skip to content

Commit fc55443

Browse files
authored
Merge pull request #21571 from Wilfred/check_type_names
fix: Stale diagnostics with rust-project.json and rustc JSON
2 parents a1f5d50 + 2cefe47 commit fc55443

File tree

1 file changed

+71
-36
lines changed

1 file changed

+71
-36
lines changed

crates/rust-analyzer/src/flycheck.rs

Lines changed: 71 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -421,11 +421,17 @@ struct FlycheckActor {
421421
diagnostics_received: DiagnosticsReceived,
422422
}
423423

424-
#[derive(PartialEq)]
424+
#[derive(PartialEq, Debug)]
425425
enum DiagnosticsReceived {
426-
Yes,
427-
No,
428-
YesAndClearedForAll,
426+
/// We started a flycheck, but we haven't seen any diagnostics yet.
427+
NotYet,
428+
/// We received a non-zero number of diagnostics from rustc or clippy (via
429+
/// cargo or custom check command). This means there were errors or
430+
/// warnings.
431+
AtLeastOne,
432+
/// We received a non-zero number of diagnostics, and the scope is
433+
/// workspace, so we've discarded the previous workspace diagnostics.
434+
AtLeastOneAndClearedWorkspace,
429435
}
430436

431437
#[allow(clippy::large_enum_variant)]
@@ -522,7 +528,7 @@ impl FlycheckActor {
522528
command_handle: None,
523529
command_receiver: None,
524530
diagnostics_cleared_for: Default::default(),
525-
diagnostics_received: DiagnosticsReceived::No,
531+
diagnostics_received: DiagnosticsReceived::NotYet,
526532
}
527533
}
528534

@@ -641,7 +647,7 @@ impl FlycheckActor {
641647
error
642648
);
643649
}
644-
if self.diagnostics_received == DiagnosticsReceived::No {
650+
if self.diagnostics_received == DiagnosticsReceived::NotYet {
645651
tracing::trace!(flycheck_id = self.id, "clearing diagnostics");
646652
// We finished without receiving any diagnostics.
647653
// Clear everything for good measure
@@ -735,41 +741,70 @@ impl FlycheckActor {
735741
flycheck_id = self.id,
736742
message = diagnostic.message,
737743
package_id = package_id.as_ref().map(|it| it.as_str()),
744+
scope = ?self.scope,
738745
"diagnostic received"
739746
);
740-
if self.diagnostics_received == DiagnosticsReceived::No {
741-
self.diagnostics_received = DiagnosticsReceived::Yes;
742-
}
743-
if let Some(package_id) = &package_id {
744-
if self.diagnostics_cleared_for.insert(package_id.clone()) {
745-
tracing::trace!(
746-
flycheck_id = self.id,
747-
package_id = package_id.as_str(),
748-
"clearing diagnostics"
749-
);
750-
self.send(FlycheckMessage::ClearDiagnostics {
747+
748+
match &self.scope {
749+
FlycheckScope::Workspace => {
750+
if self.diagnostics_received == DiagnosticsReceived::NotYet {
751+
self.send(FlycheckMessage::ClearDiagnostics {
752+
id: self.id,
753+
kind: ClearDiagnosticsKind::All(ClearScope::Workspace),
754+
});
755+
756+
self.diagnostics_received =
757+
DiagnosticsReceived::AtLeastOneAndClearedWorkspace;
758+
}
759+
760+
if let Some(package_id) = package_id {
761+
tracing::warn!(
762+
"Ignoring package label {:?} and applying diagnostics to the whole workspace",
763+
package_id
764+
);
765+
}
766+
767+
self.send(FlycheckMessage::AddDiagnostic {
751768
id: self.id,
752-
kind: ClearDiagnosticsKind::All(ClearScope::Package(
753-
package_id.clone(),
754-
)),
769+
generation: self.generation,
770+
package_id: None,
771+
workspace_root: self.root.clone(),
772+
diagnostic,
773+
});
774+
}
775+
FlycheckScope::Package { package: flycheck_package, .. } => {
776+
if self.diagnostics_received == DiagnosticsReceived::NotYet {
777+
self.diagnostics_received = DiagnosticsReceived::AtLeastOne;
778+
}
779+
780+
// If the package has been set in the diagnostic JSON, respect that. Otherwise, use the
781+
// package that the current flycheck is scoped to. This is useful when a project is
782+
// directly using rustc for its checks (e.g. custom check commands in rust-project.json).
783+
let package_id = package_id.unwrap_or(flycheck_package.clone());
784+
785+
if self.diagnostics_cleared_for.insert(package_id.clone()) {
786+
tracing::trace!(
787+
flycheck_id = self.id,
788+
package_id = package_id.as_str(),
789+
"clearing diagnostics"
790+
);
791+
self.send(FlycheckMessage::ClearDiagnostics {
792+
id: self.id,
793+
kind: ClearDiagnosticsKind::All(ClearScope::Package(
794+
package_id.clone(),
795+
)),
796+
});
797+
}
798+
799+
self.send(FlycheckMessage::AddDiagnostic {
800+
id: self.id,
801+
generation: self.generation,
802+
package_id: Some(package_id),
803+
workspace_root: self.root.clone(),
804+
diagnostic,
755805
});
756806
}
757-
} else if self.diagnostics_received
758-
!= DiagnosticsReceived::YesAndClearedForAll
759-
{
760-
self.diagnostics_received = DiagnosticsReceived::YesAndClearedForAll;
761-
self.send(FlycheckMessage::ClearDiagnostics {
762-
id: self.id,
763-
kind: ClearDiagnosticsKind::All(ClearScope::Workspace),
764-
});
765807
}
766-
self.send(FlycheckMessage::AddDiagnostic {
767-
id: self.id,
768-
generation: self.generation,
769-
package_id,
770-
workspace_root: self.root.clone(),
771-
diagnostic,
772-
});
773808
}
774809
},
775810
}
@@ -793,7 +828,7 @@ impl FlycheckActor {
793828

794829
fn clear_diagnostics_state(&mut self) {
795830
self.diagnostics_cleared_for.clear();
796-
self.diagnostics_received = DiagnosticsReceived::No;
831+
self.diagnostics_received = DiagnosticsReceived::NotYet;
797832
}
798833

799834
fn explicit_check_command(

0 commit comments

Comments
 (0)