use alloc::borrow::ToOwned;
use alloc::boxed::Box;
use alloc::format;
use alloc::string::{String, ToString};
use alloc::vec;
use alloc::vec::Vec;
use core::any::Any;
use crate::rustc_ast::node_id::NodeId;
use crate::rustc_data_structures::fx::FxIndexMap;
use crate::rustc_data_structures::sync::{DynSend, DynSync};
use crate::rustc_error_messages::MultiSpan;
use crate::rustc_lint_defs::{Lint, LintId};
use crate::rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level};
pub struct DecorateDiagCompat(
).
pub Box<dyn for<'a> FnOnce(DiagCtxtHandle<'a>, Level, &dyn Any) -> Diag<'a, ()> + 'static>,
);
impl core::fmt::Debug for DecorateDiagCompat {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("DecorateDiagCompat").finish()
}
}
impl<D: for<'a> Diagnostic<'a, ()> + DynSync + DynSend + 'static> From<D> for DecorateDiagCompat {
#[inline]
fn from(d: D) -> Self {
Self(Box::new(|dcx, level, _| d.into_diag(dcx, level)))
}
}
#[derive(Debug)]
pub struct BufferedEarlyLint {
pub span: Option<MultiSpan>,
pub node_id: NodeId,
pub lint_id: LintId,
pub diagnostic: DecorateDiagCompat,
}
#[derive(Default, Debug)]
pub struct LintBuffer {
pub map: FxIndexMap<NodeId, Vec<BufferedEarlyLint>>,
}
impl LintBuffer {
pub fn add_early_lint(&mut self, early_lint: BufferedEarlyLint) {
self.map.entry(early_lint.node_id).or_default().push(early_lint);
}
pub fn take(&mut self, id: NodeId) -> Vec<BufferedEarlyLint> {
self.map.swap_remove(&id).unwrap_or_default()
}
pub fn buffer_lint(
&mut self,
lint: &'static Lint,
node_id: NodeId,
span: impl Into<MultiSpan>,
decorate: impl Into<DecorateDiagCompat>,
) {
self.add_early_lint(BufferedEarlyLint {
lint_id: LintId::of(lint),
node_id,
span: Some(span.into()),
diagnostic: decorate.into(),
});
}
pub fn dyn_buffer_lint<
F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSync + DynSend + 'static,
>(
&mut self,
lint: &'static Lint,
node_id: NodeId,
span: impl Into<MultiSpan>,
callback: F,
) {
self.add_early_lint(BufferedEarlyLint {
lint_id: LintId::of(lint),
node_id,
span: Some(span.into()),
diagnostic: DecorateDiagCompat(Box::new(|dcx, level, _| callback(dcx, level))),
});
}
pub fn dyn_buffer_lint_any<
F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level, &dyn Any) -> Diag<'a, ()>
+ DynSend
+ DynSync
+ 'static,
>(
&mut self,
lint: &'static Lint,
node_id: NodeId,
span: impl Into<MultiSpan>,
callback: F,
) {
self.add_early_lint(BufferedEarlyLint {
lint_id: LintId::of(lint),
node_id,
span: Some(span.into()),
diagnostic: DecorateDiagCompat(Box::new(callback)),
});
}
}