turbopack_core/diagnostics/
mod.rs1use std::cmp::Ordering;
2
3use anyhow::Result;
4use async_trait::async_trait;
5use auto_hash_map::AutoSet;
6use turbo_rcstr::RcStr;
7use turbo_tasks::{CollectiblesSource, FxIndexMap, ResolvedVc, Upcast, Vc, emit};
8
9#[turbo_tasks::value(serialization = "none")]
10#[derive(Clone, Debug)]
11pub struct PlainDiagnostic {
12 pub category: RcStr,
13 pub name: RcStr,
14 pub payload: FxIndexMap<RcStr, RcStr>,
15}
16
17impl Ord for PlainDiagnostic {
18 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
19 self.name
20 .cmp(&other.name)
21 .then_with(|| self.category.cmp(&other.category))
22 .then_with(|| self.payload.len().cmp(&other.payload.len()))
23 .then_with(|| {
24 for ((a_key, a_value), (b_key, b_value)) in
25 self.payload.iter().zip(other.payload.iter())
26 {
27 match a_key.cmp(b_key) {
28 Ordering::Equal => {}
29 other => return other,
30 }
31 match a_value.cmp(b_value) {
32 Ordering::Equal => {}
33 other => return other,
34 }
35 }
36 Ordering::Equal
37 })
38 }
39}
40
41impl PartialOrd for PlainDiagnostic {
42 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
43 Some(self.cmp(other))
44 }
45}
46
47#[turbo_tasks::value(transparent)]
48pub struct DiagnosticPayload(pub FxIndexMap<RcStr, RcStr>);
49
50#[turbo_tasks::value_trait]
53pub trait Diagnostic {
54 #[turbo_tasks::function]
61 fn category(&self) -> Vc<RcStr>;
62 #[turbo_tasks::function]
64 fn name(&self) -> Vc<RcStr>;
65 #[turbo_tasks::function]
67 fn payload(&self) -> Vc<DiagnosticPayload>;
68
69 #[turbo_tasks::function]
70 async fn into_plain(self: Vc<Self>) -> Result<Vc<PlainDiagnostic>> {
71 Ok(PlainDiagnostic {
72 category: self.category().owned().await?,
73 name: self.name().owned().await?,
74 payload: self.payload().owned().await?,
75 }
76 .cell())
77 }
78}
79
80pub trait DiagnosticExt {
81 fn emit(self);
82}
83
84impl<T> DiagnosticExt for ResolvedVc<T>
85where
86 T: Upcast<Box<dyn Diagnostic>>,
87{
88 fn emit(self) {
89 let diagnostic = ResolvedVc::upcast::<Box<dyn Diagnostic>>(self);
90 emit(diagnostic);
91 }
92}
93
94#[async_trait]
95pub trait DiagnosticContextExt
96where
97 Self: Sized,
98{
99 async fn peek_diagnostics(self) -> Result<CapturedDiagnostics>;
100}
101
102#[async_trait]
103impl<T> DiagnosticContextExt for T
104where
105 T: CollectiblesSource + Copy + Send,
106{
107 async fn peek_diagnostics(self) -> Result<CapturedDiagnostics> {
108 Ok(CapturedDiagnostics {
109 diagnostics: self.peek_collectibles(),
110 })
111 }
112}
113
114#[derive(Debug)]
117#[turbo_tasks::value]
118pub struct CapturedDiagnostics {
119 pub diagnostics: AutoSet<ResolvedVc<Box<dyn Diagnostic>>>,
120}