1use codespan_reporting::diagnostic::Diagnostic;
2use codespan_reporting::files::{Error, SimpleFile};
3use std::rc::Rc;
4
5#[derive(Debug, Default)]
7pub struct Codebase {
8 config: codespan_reporting::term::Config,
9 files: Vec<SimpleFile<String, Rc<str>>>,
10 errors: usize,
11 warnings: usize,
12}
13
14impl Codebase {
15 pub fn new() -> Self {
17 Self::default()
18 }
19
20 pub fn add(&mut self, name: String, source: String) -> usize {
23 let file_id = self.files.len();
24 self.files.push(SimpleFile::new(name, Rc::from(source)));
25 file_id
26 }
27
28 pub fn get(&self, file_id: usize) -> Result<&SimpleFile<String, Rc<str>>, Error> {
30 self.files.get(file_id).ok_or(Error::FileMissing)
31 }
32
33 pub fn emit(&mut self, diagnostic: Diagnostic<usize>) {
35 match diagnostic.severity {
36 codespan_reporting::diagnostic::Severity::Bug => (),
37 codespan_reporting::diagnostic::Severity::Error => self.errors += 1,
38 codespan_reporting::diagnostic::Severity::Warning => self.warnings += 1,
39 codespan_reporting::diagnostic::Severity::Note => (),
40 codespan_reporting::diagnostic::Severity::Help => (),
41 };
42 let mut writer = codespan_reporting::term::termcolor::StandardStream::stderr(
43 codespan_reporting::term::termcolor::ColorChoice::Auto,
44 );
45 codespan_reporting::term::emit(&mut writer, &self.config, self, &diagnostic)
46 .expect("internal error");
47 }
48
49 pub fn files(&self) -> &Vec<SimpleFile<String, Rc<str>>> {
50 &self.files
51 }
52
53 pub fn errors(&self) -> usize {
55 self.errors
56 }
57
58 pub fn warnings(&self) -> usize {
60 self.warnings
61 }
62}
63
64impl<'a> codespan_reporting::files::Files<'a> for Codebase {
65 type FileId = usize;
66 type Name = String;
67 type Source = &'a str;
68
69 fn name(&self, file_id: usize) -> Result<String, Error> {
70 Ok(self.get(file_id)?.name().clone())
71 }
72
73 fn source(&self, file_id: usize) -> Result<&str, Error> {
74 Ok(self.get(file_id)?.source().as_ref())
75 }
76
77 fn line_index(&self, file_id: usize, byte_index: usize) -> Result<usize, Error> {
78 self.get(file_id)?.line_index((), byte_index)
79 }
80
81 fn line_range(
82 &self,
83 file_id: usize,
84 line_index: usize,
85 ) -> Result<std::ops::Range<usize>, Error> {
86 self.get(file_id)?.line_range((), line_index)
87 }
88}