use crate::checkstyle::api::error::{CheckstyleError, CheckstyleResult};
use crate::checkstyle::api::event::AuditEvent;
use crate::checkstyle::api::listener::AuditListener;
use std::io::{self, Write};
use std::sync::Mutex;
pub struct DefaultLogger {
output: Mutex<Box<dyn Write + Send>>,
}
impl DefaultLogger {
pub fn new() -> Self {
Self {
output: Mutex::new(Box::new(io::stdout())),
}
}
pub fn with_writer(writer: Box<dyn Write + Send>) -> Self {
Self {
output: Mutex::new(writer),
}
}
}
impl Default for DefaultLogger {
fn default() -> Self {
Self::new()
}
}
impl AuditListener for DefaultLogger {
fn audit_started(&mut self, _event: &AuditEvent) -> CheckstyleResult<()> {
Ok(())
}
fn audit_finished(&mut self, _event: &AuditEvent) -> CheckstyleResult<()> {
Ok(())
}
fn file_started(&mut self, _event: &AuditEvent) -> CheckstyleResult<()> {
Ok(())
}
fn file_finished(&mut self, _event: &AuditEvent) -> CheckstyleResult<()> {
Ok(())
}
fn add_error(&mut self, event: &AuditEvent) -> CheckstyleResult<()> {
if let Some(violation) = &event.violation {
if violation.severity_level == crate::checkstyle::api::event::SeverityLevel::Ignore {
return Ok(());
}
let file_name = event
.file
.as_ref()
.map(|f| f.display().to_string())
.unwrap_or_else(|| "unknown".to_string());
let severity_str = match violation.severity_level {
crate::checkstyle::api::event::SeverityLevel::Warning => "WARN",
crate::checkstyle::api::event::SeverityLevel::Error => "ERROR",
crate::checkstyle::api::event::SeverityLevel::Info => "INFO",
crate::checkstyle::api::event::SeverityLevel::Ignore => "IGNORE", };
let mut output = self.output.lock().unwrap();
if violation.column_no > 0 {
writeln!(
output,
"[{}] {}:{}:{}: {} [{}]",
severity_str,
file_name,
violation.line_no,
violation.column_no,
violation.get_message(),
violation.module_id
)
.map_err(CheckstyleError::Io)?;
} else {
writeln!(
output,
"[{}] {}:{}: {} [{}]",
severity_str,
file_name,
violation.line_no,
violation.get_message(),
violation.module_id
)
.map_err(CheckstyleError::Io)?;
}
}
Ok(())
}
fn add_exception(
&mut self,
event: &AuditEvent,
error: &dyn std::error::Error,
) -> CheckstyleResult<()> {
let file_name = event
.file
.as_ref()
.map(|f| f.display().to_string())
.unwrap_or_else(|| "unknown".to_string());
let mut output = self.output.lock().unwrap();
writeln!(
output,
"[ERROR] {file_name}: Exception occurred: {error}"
)
.map_err(CheckstyleError::Io)?;
Ok(())
}
}