mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
docs(diagnostics): fully document oxc_diagnostics (#5865)
Just a step in my mission to document our entire API
This commit is contained in:
parent
4e37d18b2e
commit
83ca7f56cd
8 changed files with 301 additions and 7 deletions
|
|
@ -18,14 +18,36 @@ use crate::graphical_theme::GraphicalTheme;
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct GraphicalReportHandler {
|
||||
/// How to render links.
|
||||
///
|
||||
/// Default: [`LinkStyle::Link`]
|
||||
pub(crate) links: LinkStyle,
|
||||
/// Terminal width to wrap at.
|
||||
///
|
||||
/// Default: `400`
|
||||
pub(crate) termwidth: usize,
|
||||
/// How to style reports
|
||||
pub(crate) theme: GraphicalTheme,
|
||||
pub(crate) footer: Option<String>,
|
||||
/// Number of source lines to render before/after the line(s) covered by errors.
|
||||
///
|
||||
/// Default: `1`
|
||||
pub(crate) context_lines: usize,
|
||||
/// Tab print width
|
||||
///
|
||||
/// Default: `4`
|
||||
pub(crate) tab_width: usize,
|
||||
/// Unused.
|
||||
pub(crate) with_cause_chain: bool,
|
||||
/// Whether to wrap lines to fit the width.
|
||||
///
|
||||
/// Default: `true`
|
||||
pub(crate) wrap_lines: bool,
|
||||
/// Whether to break words during wrapping.
|
||||
///
|
||||
/// When `false`, line breaks will happen before the first word that would overflow `termwidth`.
|
||||
///
|
||||
/// Default: `true`
|
||||
pub(crate) break_words: bool,
|
||||
pub(crate) word_separator: Option<textwrap::WordSeparator>,
|
||||
pub(crate) word_splitter: Option<textwrap::WordSplitter>,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@ and the
|
|||
|
||||
You can create your own custom graphical theme using this type, or you can use
|
||||
one of the predefined ones using the methods below.
|
||||
|
||||
When created by [`Default::default`], themes are automatically selected based on the `NO_COLOR`
|
||||
environment variable and whether the process is running in a terminal.
|
||||
*/
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct GraphicalTheme {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,52 @@
|
|||
//! Diagnostics Wrapper
|
||||
//! Exports `miette`
|
||||
//! Error data types and utilities for handling/reporting them.
|
||||
//!
|
||||
//! The main type in this module is [`OxcDiagnostic`], which is used by all other oxc tools to
|
||||
//! report problems. It implements [miette]'s [`Diagnostic`] trait, making it compatible with other
|
||||
//! tooling you may be using.
|
||||
//!
|
||||
//! ```rust
|
||||
//! use oxc_diagnostics::{OxcDiagnostic, Result};
|
||||
//! fn my_tool() -> Result<()> {
|
||||
//! try_something().map_err(|e| OxcDiagnostic::error(e.to_string()))?;
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! See the [miette] documentation for more information on how to interact with diagnostics.
|
||||
//!
|
||||
//! ## Reporting
|
||||
//! If you are writing your own tools that may produce their own errors, you can use
|
||||
//! [`DiagnosticService`] to format and render them to a string or a stream. It can receive
|
||||
//! [`Error`]s over a multi-producer, single consumer
|
||||
//!
|
||||
//! ```
|
||||
//! use std::{sync::Arc, thread};
|
||||
//! use oxc_diagnostics::{DiagnosticService, Error, OxcDiagnostic};
|
||||
//!
|
||||
//! fn my_tool() -> Result<()> {
|
||||
//! try_something().map_err(|e| OxcDiagnostic::error(e.to_string()))?;
|
||||
//! Ok(())
|
||||
//! }
|
||||
//!
|
||||
//! let mut service = DiagnosticService::default();
|
||||
//! let mut sender = service.sender().clone();
|
||||
//!
|
||||
//! thread::spawn(move || {
|
||||
//! let file_path_being_processed = PathBuf::from("file.txt");
|
||||
//! let file_being_processed = Arc::new(NamedSource::new(file_path_being_processed.clone()));
|
||||
//!
|
||||
//! for _ in 0..10 {
|
||||
//! if let Err(diagnostic) = my_tool() {
|
||||
//! let report = diagnostic.with_source_code(Arc::clone(&file_being_processed));
|
||||
//! sender.send(Some(file_path_being_processed, vec![Error::new(e)]));
|
||||
//! }
|
||||
//! // send None to stop the service
|
||||
//! sender.send(None);
|
||||
//! }
|
||||
//! });
|
||||
//!
|
||||
//! service.run();
|
||||
//! ```
|
||||
|
||||
mod graphic_reporter;
|
||||
mod graphical_theme;
|
||||
|
|
@ -26,6 +73,9 @@ pub type Result<T> = std::result::Result<T, OxcDiagnostic>;
|
|||
use miette::{Diagnostic, SourceCode};
|
||||
pub use miette::{LabeledSpan, NamedSource};
|
||||
|
||||
/// Describes an error or warning that occurred.
|
||||
///
|
||||
/// Used by all oxc tools.
|
||||
#[derive(Debug, Clone)]
|
||||
#[must_use]
|
||||
pub struct OxcDiagnostic {
|
||||
|
|
@ -89,14 +139,19 @@ impl fmt::Display for OxcDiagnostic {
|
|||
impl std::error::Error for OxcDiagnostic {}
|
||||
|
||||
impl Diagnostic for OxcDiagnostic {
|
||||
/// The secondary help message.
|
||||
fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
|
||||
self.help.as_ref().map(Box::new).map(|c| c as Box<dyn Display>)
|
||||
}
|
||||
|
||||
/// The severity level of this diagnostic.
|
||||
///
|
||||
/// Diagnostics with missing severity levels should be treated as [errors](Severity::Error).
|
||||
fn severity(&self) -> Option<Severity> {
|
||||
Some(self.severity)
|
||||
}
|
||||
|
||||
/// Labels covering problematic portions of source code.
|
||||
fn labels(&self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + '_>> {
|
||||
self.labels
|
||||
.as_ref()
|
||||
|
|
@ -105,16 +160,21 @@ impl Diagnostic for OxcDiagnostic {
|
|||
.map(|b| b as Box<dyn Iterator<Item = LabeledSpan>>)
|
||||
}
|
||||
|
||||
/// An error code uniquely identifying this diagnostic.
|
||||
///
|
||||
/// Note that codes may be scoped, which will be rendered as `scope(code)`.
|
||||
fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
|
||||
self.code.is_some().then(|| Box::new(&self.code) as Box<dyn Display>)
|
||||
}
|
||||
|
||||
/// A URL that provides more information about the problem that occurred.
|
||||
fn url<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
|
||||
self.url.as_ref().map(Box::new).map(|c| c as Box<dyn Display>)
|
||||
}
|
||||
}
|
||||
|
||||
impl OxcDiagnostic {
|
||||
/// Create new an error-level [`OxcDiagnostic`].
|
||||
pub fn error<T: Into<Cow<'static, str>>>(message: T) -> Self {
|
||||
Self {
|
||||
inner: Box::new(OxcDiagnosticInner {
|
||||
|
|
@ -128,6 +188,7 @@ impl OxcDiagnostic {
|
|||
}
|
||||
}
|
||||
|
||||
/// Create new a warning-level [`OxcDiagnostic`].
|
||||
pub fn warn<T: Into<Cow<'static, str>>>(message: T) -> Self {
|
||||
Self {
|
||||
inner: Box::new(OxcDiagnosticInner {
|
||||
|
|
@ -141,6 +202,9 @@ impl OxcDiagnostic {
|
|||
}
|
||||
}
|
||||
|
||||
/// Add a scoped error code to this diagnostic.
|
||||
///
|
||||
/// This is a shorthand for `with_error_code_scope(scope).with_error_code_num(number)`.
|
||||
#[inline]
|
||||
pub fn with_error_code<T: Into<Cow<'static, str>>, U: Into<Cow<'static, str>>>(
|
||||
self,
|
||||
|
|
@ -150,6 +214,9 @@ impl OxcDiagnostic {
|
|||
self.with_error_code_scope(scope).with_error_code_num(number)
|
||||
}
|
||||
|
||||
/// Add an error code scope to this diagnostic.
|
||||
///
|
||||
/// Use [`OxcDiagnostic::with_error_code`] to set both the scope and number at once.
|
||||
#[inline]
|
||||
pub fn with_error_code_scope<T: Into<Cow<'static, str>>>(mut self, code_scope: T) -> Self {
|
||||
self.inner.code.scope = match self.inner.code.scope {
|
||||
|
|
@ -164,6 +231,9 @@ impl OxcDiagnostic {
|
|||
self
|
||||
}
|
||||
|
||||
/// Add an error code number to this diagnostic.
|
||||
///
|
||||
/// Use [`OxcDiagnostic::with_error_code`] to set both the scope and number at once.
|
||||
#[inline]
|
||||
pub fn with_error_code_num<T: Into<Cow<'static, str>>>(mut self, code_num: T) -> Self {
|
||||
self.inner.code.number = match self.inner.code.number {
|
||||
|
|
@ -178,21 +248,63 @@ impl OxcDiagnostic {
|
|||
self
|
||||
}
|
||||
|
||||
/// Set the severity level of this diagnostic.
|
||||
///
|
||||
/// Use [`OxcDiagnostic::error`] or [`OxcDiagnostic::warn`] to create a diagnostic at the
|
||||
/// severity you want.
|
||||
pub fn with_severity(mut self, severity: Severity) -> Self {
|
||||
self.inner.severity = severity;
|
||||
self
|
||||
}
|
||||
|
||||
/// Suggest a possible solution for a problem to the user.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```
|
||||
/// use std::path::PathBuf;
|
||||
/// use oxc_diagnostics::OxcDiagnostic
|
||||
///
|
||||
/// let config_file_path = Path::from("config.json");
|
||||
/// if !config_file_path.exists() {
|
||||
/// return Err(OxcDiagnostic::error("No config file found")
|
||||
/// .with_help("Run my_tool --init to set up a new config file"));
|
||||
/// }
|
||||
/// ```
|
||||
pub fn with_help<T: Into<Cow<'static, str>>>(mut self, help: T) -> Self {
|
||||
self.inner.help = Some(help.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the label covering a problematic portion of source code.
|
||||
///
|
||||
/// Existing labels will be removed. Use [`OxcDiagnostic::and_label`] append a label instead.
|
||||
///
|
||||
/// You need to add some source code to this diagnostic (using
|
||||
/// [`OxcDiagnostic::with_source_code`]) for this to actually be useful. Use
|
||||
/// [`OxcDiagnostic::with_labels`] to add multiple labels all at once.
|
||||
///
|
||||
/// Note that this pairs nicely with [`oxc_span::Span`], particularly the [`label`] method.
|
||||
///
|
||||
/// [`oxc_span::Span`]: https://docs.rs/oxc_span/latest/oxc_span/struct.Span.html
|
||||
/// [`label`]: https://docs.rs/oxc_span/latest/oxc_span/struct.Span.html#method.label
|
||||
pub fn with_label<T: Into<LabeledSpan>>(mut self, label: T) -> Self {
|
||||
self.inner.labels = Some(vec![label.into()]);
|
||||
self
|
||||
}
|
||||
|
||||
/// Add multiple labels covering problematic portions of source code.
|
||||
///
|
||||
/// Existing labels will be removed. Use [`OxcDiagnostic::and_labels`] to append labels
|
||||
/// instead.
|
||||
///
|
||||
/// You need to add some source code using [`OxcDiagnostic::with_source_code`] for this to
|
||||
/// actually be useful. If you only have a single label, consider using
|
||||
/// [`OxcDiagnostic::with_label`] instead.
|
||||
///
|
||||
/// Note that this pairs nicely with [`oxc_span::Span`], particularly the [`label`] method.
|
||||
///
|
||||
/// [`oxc_span::Span`]: https://docs.rs/oxc_span/latest/oxc_span/struct.Span.html
|
||||
/// [`label`]: https://docs.rs/oxc_span/latest/oxc_span/struct.Span.html#method.label
|
||||
pub fn with_labels<L: Into<LabeledSpan>, T: IntoIterator<Item = L>>(
|
||||
mut self,
|
||||
labels: T,
|
||||
|
|
@ -201,6 +313,7 @@ impl OxcDiagnostic {
|
|||
self
|
||||
}
|
||||
|
||||
/// Add a label to this diagnostic without clobbering existing labels.
|
||||
pub fn and_label<T: Into<LabeledSpan>>(mut self, label: T) -> Self {
|
||||
let mut labels = self.inner.labels.unwrap_or_default();
|
||||
labels.push(label.into());
|
||||
|
|
@ -208,6 +321,7 @@ impl OxcDiagnostic {
|
|||
self
|
||||
}
|
||||
|
||||
/// Add multiple labels to this diagnostic without clobbering existing labels.
|
||||
pub fn and_labels<L: Into<LabeledSpan>, T: IntoIterator<Item = L>>(
|
||||
mut self,
|
||||
labels: T,
|
||||
|
|
@ -218,11 +332,15 @@ impl OxcDiagnostic {
|
|||
self
|
||||
}
|
||||
|
||||
/// Add a URL that provides more information about this diagnostic.
|
||||
pub fn with_url<S: Into<Cow<'static, str>>>(mut self, url: S) -> Self {
|
||||
self.inner.url = Some(url.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Add source code to this diagnostic and convert it into an [`Error`].
|
||||
///
|
||||
/// You should use a [`NamedSource`] if you have a file name as well as the source code.
|
||||
pub fn with_source_code<T: SourceCode + Send + Sync + 'static>(self, code: T) -> Error {
|
||||
Error::from(self).with_source_code(code)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ use std::{
|
|||
use super::{writer, DiagnosticReporter, Info};
|
||||
use crate::{Error, Severity};
|
||||
|
||||
/// Formats reports using [GitHub Actions
|
||||
/// annotations](https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message). Useful for reporting in CI.
|
||||
pub struct GithubReporter {
|
||||
writer: BufWriter<Stdout>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@ use std::io::{BufWriter, ErrorKind, Stdout, Write};
|
|||
use super::{writer, DiagnosticReporter};
|
||||
use crate::{Error, GraphicalReportHandler};
|
||||
|
||||
/// Pretty-prints diagnostics. Primarily meant for human-readable output in a terminal.
|
||||
///
|
||||
/// See [`GraphicalReportHandler`] for how to configure colors, context lines, etc.
|
||||
pub struct GraphicalReporter {
|
||||
handler: GraphicalReportHandler,
|
||||
writer: BufWriter<Stdout>,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,10 @@ use miette::JSONReportHandler;
|
|||
use super::DiagnosticReporter;
|
||||
use crate::Error;
|
||||
|
||||
/// Renders reports as a JSON array of objects.
|
||||
///
|
||||
/// Note that, due to syntactic restrictions of JSON arrays, this reporter waits until all
|
||||
/// diagnostics have been reported before writing them to the output stream.
|
||||
#[derive(Default)]
|
||||
pub struct JsonReporter {
|
||||
diagnostics: Vec<Error>,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
//! [Reporters](DiagnosticReporter) for rendering and writing diagnostics.
|
||||
|
||||
mod checkstyle;
|
||||
mod github;
|
||||
mod graphical;
|
||||
|
|
@ -18,9 +20,73 @@ fn writer() -> BufWriter<Stdout> {
|
|||
BufWriter::new(std::io::stdout())
|
||||
}
|
||||
|
||||
/// Reporters are responsible for rendering diagnostics to some format and writing them to some
|
||||
/// form of output stream.
|
||||
///
|
||||
/// Reporters get used by [`DiagnosticService`](crate::service::DiagnosticService) when they
|
||||
/// receive diagnostics.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```
|
||||
/// use std::io::{self, Write, BufWriter, Stderr};
|
||||
/// use oxc_diagnostics::{DiagnosticReporter, Error, Severity};
|
||||
///
|
||||
/// pub struct BufReporter {
|
||||
/// writer: BufWriter<Stderr>,
|
||||
/// }
|
||||
///
|
||||
/// impl Default for BufReporter {
|
||||
/// fn default() -> Self {
|
||||
/// Self { writer: BufWriter::new(io::stderr()) }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl DiagnosticReporter for BufferedReporter {
|
||||
/// // flush all remaining bytes when no more diagnostics will be reported
|
||||
/// fn finish(&mut self) {
|
||||
/// self.writer.flush().unwrap();
|
||||
/// }
|
||||
///
|
||||
/// // write rendered reports to stderr
|
||||
/// fn render_diagnostics(&mut self, s: &[u8]) {
|
||||
/// self.writer.write_all(s).unwrap();
|
||||
/// }
|
||||
///
|
||||
/// // render diagnostics to a simple Apache-like log format
|
||||
/// fn render_error(&mut self, error: Error) -> Option<String> {
|
||||
/// let level = match error.severity().unwrap_or_default() {
|
||||
/// Severity::Error => "ERROR",
|
||||
/// Severity::Warning => "WARN",
|
||||
/// Severity::Advice => "INFO",
|
||||
/// };
|
||||
/// let rendered = format!("[{level}]: {error}");
|
||||
///
|
||||
/// Some(rendered)
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub trait DiagnosticReporter {
|
||||
/// Lifecycle hook that gets called when no more diagnostics will be reported.
|
||||
///
|
||||
/// Used primarily for flushing output stream buffers, but you don't just have to use it for
|
||||
/// that. Some reporters (e.g. [`JSONReporter`]) store all diagnostics in memory, then write them
|
||||
/// all at once.
|
||||
///
|
||||
/// While this method _should_ only ever be called a single time, this is not a guarantee
|
||||
/// upheld in Oxc's API. Do not rely on this behavior.
|
||||
///
|
||||
/// [`JSONReporter`]: crate::reporter::JsonReporter
|
||||
fn finish(&mut self);
|
||||
|
||||
/// Write a rendered collection of diagnostics to this reporter's output stream.
|
||||
fn render_diagnostics(&mut self, s: &[u8]);
|
||||
|
||||
/// Render a diagnostic into this reporter's desired format. For example, a JSONLinesReporter
|
||||
/// might return a stringified JSON object on a single line. Returns [`None`] to skip reporting
|
||||
/// of this diagnostic.
|
||||
///
|
||||
/// Reporters should not use this method to write diagnostics to their output stream. That
|
||||
/// should be done in [`render_diagnostics`](DiagnosticReporter::render_diagnostics).
|
||||
fn render_error(&mut self, error: Error) -> Option<String>;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,38 @@ pub type DiagnosticTuple = (PathBuf, Vec<Error>);
|
|||
pub type DiagnosticSender = mpsc::Sender<Option<DiagnosticTuple>>;
|
||||
pub type DiagnosticReceiver = mpsc::Receiver<Option<DiagnosticTuple>>;
|
||||
|
||||
/// Listens for diagnostics sent over a [channel](DiagnosticSender) by some job, and
|
||||
/// formats/reports them to the user.
|
||||
///
|
||||
/// [`DiagnosticService`] is designed to support multi-threaded jobs that may produce
|
||||
/// reports. These jobs can send [messages](DiagnosticTuple) to the service over its
|
||||
/// multi-producer, single-consumer [channel](DiagnosticService::sender).
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// use std::thread;
|
||||
/// use oxc_diagnostics::{Error, OxcDiagnostic, DiagnosticService};
|
||||
///
|
||||
/// // By default, services will pretty-print diagnostics to the console
|
||||
/// let mut service = DiagnosticService::default();
|
||||
/// // Get a clone of the sender to send diagnostics to the service
|
||||
/// let mut sender = service.sender().clone();
|
||||
///
|
||||
/// // Spawn a thread that does work and reports diagnostics
|
||||
/// thread::spawn(move || {
|
||||
/// sender.send(Some((
|
||||
/// PathBuf::from("file.txt"),
|
||||
/// vec![Error::new(OxcDiagnostic::error("Something went wrong"))],
|
||||
/// )));
|
||||
///
|
||||
/// // Send `None` to have the service stop listening for messages.
|
||||
/// // If you don't ever send `None`, the service will poll forever.
|
||||
/// sender.send(None);
|
||||
/// });
|
||||
///
|
||||
/// // Listen for and process messages
|
||||
/// service.run()
|
||||
/// ```
|
||||
pub struct DiagnosticService {
|
||||
reporter: Box<dyn DiagnosticReporter>,
|
||||
|
||||
|
|
@ -41,9 +73,20 @@ pub struct DiagnosticService {
|
|||
|
||||
impl Default for DiagnosticService {
|
||||
fn default() -> Self {
|
||||
Self::new(GraphicalReporter::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl DiagnosticService {
|
||||
/// Create a new [`DiagnosticService`] that will render and report diagnostics using the
|
||||
/// provided [`DiagnosticReporter`].
|
||||
///
|
||||
/// TODO(@DonIsaac): make `DiagnosticReporter` public so oxc consumers can create their own
|
||||
/// implementations.
|
||||
pub(crate) fn new<R: DiagnosticReporter + 'static>(reporter: R) -> Self {
|
||||
let (sender, receiver) = mpsc::channel();
|
||||
Self {
|
||||
reporter: Box::<GraphicalReporter>::default(),
|
||||
reporter: Box::new(reporter) as Box<dyn DiagnosticReporter>,
|
||||
quiet: false,
|
||||
silent: false,
|
||||
max_warnings: None,
|
||||
|
|
@ -53,9 +96,8 @@ impl Default for DiagnosticService {
|
|||
receiver,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DiagnosticService {
|
||||
/// Configure this service to format reports as a JSON array of objects.
|
||||
pub fn set_json_reporter(&mut self) {
|
||||
self.reporter = Box::<JsonReporter>::default();
|
||||
}
|
||||
|
|
@ -68,49 +110,83 @@ impl DiagnosticService {
|
|||
self.reporter = Box::<CheckstyleReporter>::default();
|
||||
}
|
||||
|
||||
/// Configure this service to formats reports using [GitHub Actions
|
||||
/// annotations](https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message).
|
||||
pub fn set_github_reporter(&mut self) {
|
||||
self.reporter = Box::<GithubReporter>::default();
|
||||
}
|
||||
|
||||
/// Set to `true` to only report errors and ignore warnings.
|
||||
///
|
||||
/// Use [`with_silent`](DiagnosticService::with_silent) to disable reporting entirely.
|
||||
///
|
||||
/// Default: `false`
|
||||
#[must_use]
|
||||
pub fn with_quiet(mut self, yes: bool) -> Self {
|
||||
self.quiet = yes;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set to `true` to disable reporting entirely.
|
||||
///
|
||||
/// Use [`with_quiet`](DiagnosticService::with_quiet) to only disable reporting on warnings.
|
||||
///
|
||||
/// Default is `false`.
|
||||
#[must_use]
|
||||
pub fn with_silent(mut self, yes: bool) -> Self {
|
||||
self.silent = yes;
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify a warning threshold, which can be used to force exit with an error status if there
|
||||
/// are too many warning-level rule violations in your project. Errors do not count towards the
|
||||
/// warning limit.
|
||||
///
|
||||
/// Use [`max_warnings_exceeded`](DiagnosticService::max_warnings_exceeded) to check if too
|
||||
/// many warnings have been received.
|
||||
///
|
||||
/// Default: [`None`]
|
||||
#[must_use]
|
||||
pub fn with_max_warnings(mut self, max_warnings: Option<usize>) -> Self {
|
||||
self.max_warnings = max_warnings;
|
||||
self
|
||||
}
|
||||
|
||||
/// Channel for sending [diagnostic messages] to the service.
|
||||
///
|
||||
/// The service will only start processing diagnostics after [`run`](DiagnosticService::run)
|
||||
/// has been called.
|
||||
///
|
||||
/// [diagnostics]: DiagnosticTuple
|
||||
pub fn sender(&self) -> &DiagnosticSender {
|
||||
&self.sender
|
||||
}
|
||||
|
||||
/// Get the number of warning-level diagnostics received.
|
||||
pub fn warnings_count(&self) -> usize {
|
||||
self.warnings_count.get()
|
||||
}
|
||||
|
||||
/// Get the number of error-level diagnostics received.
|
||||
pub fn errors_count(&self) -> usize {
|
||||
self.errors_count.get()
|
||||
}
|
||||
|
||||
/// Check if the max warning threshold, as set by
|
||||
/// [`with_max_warnings`](DiagnosticService::with_max_warnings), has been exceeded.
|
||||
pub fn max_warnings_exceeded(&self) -> bool {
|
||||
self.max_warnings.map_or(false, |max_warnings| self.warnings_count.get() > max_warnings)
|
||||
}
|
||||
|
||||
pub fn wrap_diagnostics(
|
||||
path: &Path,
|
||||
/// Wrap [diagnostics] with the source code and path, converting them into [Error]s.
|
||||
///
|
||||
/// [diagnostics]: OxcDiagnostic
|
||||
pub fn wrap_diagnostics<P: AsRef<Path>>(
|
||||
path: P,
|
||||
source_text: &str,
|
||||
diagnostics: Vec<OxcDiagnostic>,
|
||||
) -> (PathBuf, Vec<Error>) {
|
||||
let path = path.as_ref();
|
||||
let source = Arc::new(NamedSource::new(path.to_string_lossy(), source_text.to_owned()));
|
||||
let diagnostics = diagnostics
|
||||
.into_iter()
|
||||
|
|
|
|||
Loading…
Reference in a new issue