use codespan_reporting::diagnostic::Diagnostic;
use codespan_reporting::files::{Error, SimpleFile};
use std::rc::Rc;
#[derive(Debug, Default)]
pub struct Codebase {
config: codespan_reporting::term::Config,
files: Vec<SimpleFile<String, Rc<str>>>,
errors: usize,
warnings: usize,
}
impl Codebase {
pub fn new() -> Self {
Self::default()
}
pub fn add(&mut self, name: String, source: String) -> usize {
let file_id = self.files.len();
self.files.push(SimpleFile::new(name, Rc::from(source)));
file_id
}
pub fn get(&self, file_id: usize) -> Result<&SimpleFile<String, Rc<str>>, Error> {
self.files.get(file_id).ok_or(Error::FileMissing)
}
pub fn emit(&mut self, diagnostic: Diagnostic<usize>) {
match diagnostic.severity {
codespan_reporting::diagnostic::Severity::Bug => (),
codespan_reporting::diagnostic::Severity::Error => self.errors += 1,
codespan_reporting::diagnostic::Severity::Warning => self.warnings += 1,
codespan_reporting::diagnostic::Severity::Note => (),
codespan_reporting::diagnostic::Severity::Help => (),
};
let mut writer = codespan_reporting::term::termcolor::StandardStream::stderr(
codespan_reporting::term::termcolor::ColorChoice::Auto,
);
codespan_reporting::term::emit(&mut writer, &self.config, self, &diagnostic)
.expect("internal error");
}
pub fn files(&self) -> &Vec<SimpleFile<String, Rc<str>>> {
&self.files
}
pub fn errors(&self) -> usize {
self.errors
}
pub fn warnings(&self) -> usize {
self.warnings
}
}
impl<'a> codespan_reporting::files::Files<'a> for Codebase {
type FileId = usize;
type Name = String;
type Source = &'a str;
fn name(&self, file_id: usize) -> Result<String, Error> {
Ok(self.get(file_id)?.name().clone())
}
fn source(&self, file_id: usize) -> Result<&str, Error> {
Ok(self.get(file_id)?.source().as_ref())
}
fn line_index(&self, file_id: usize, byte_index: usize) -> Result<usize, Error> {
self.get(file_id)?.line_index((), byte_index)
}
fn line_range(
&self,
file_id: usize,
line_index: usize,
) -> Result<std::ops::Range<usize>, Error> {
self.get(file_id)?.line_range((), line_index)
}
}