circom-lsp-program-structure 2.1.5

Support crate for circom-lsp
Documentation
use super::error_code::ReportCode;
use super::file_definition::{FileID, FileLibrary, FileLocation};
use codespan_reporting::diagnostic::{Diagnostic, Label};
use codespan_reporting::term;

pub type ReportCollection = Vec<Report>;
pub type DiagnosticCode = String;
type ReportLabel = Label<FileID>;
type ReportNote = String;

#[derive(Copy, Clone)]
pub enum MessageCategory {
    Error,
    Warning,
}
impl MessageCategory {
    fn is_error(&self) -> bool {
        use MessageCategory::*;
        match self {
            Error => true,
            _ => false,
        }
    }
    fn is_warning(&self) -> bool {
        use MessageCategory::*;
        match self {
            Warning => true,
            _ => false,
        }
    }
}

#[derive(Clone)]
pub struct Report {
    category: MessageCategory,
    error_message: String,
    error_code: ReportCode,
    primary: Vec<ReportLabel>,
    secondary: Vec<ReportLabel>,
    notes: Vec<ReportNote>,
}
impl Report {
    fn new(category: MessageCategory, error_message: String, error_code: ReportCode) -> Report {
        Report {
            category,
            error_message,
            error_code,
            primary: Vec::new(),
            secondary: Vec::new(),
            notes: Vec::new(),
        }
    }
    pub fn print_reports(reports: &[Report], file_library: &FileLibrary) {
        use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
        let writer = StandardStream::stderr(ColorChoice::Always);
        let config = term::Config::default();
        let mut diagnostics = Vec::new();
        let files = file_library.to_storage();
        for report in reports.iter() {
            diagnostics.push(report.to_diagnostic());
        }
        for diagnostic in diagnostics.iter() {
            let print_result = term::emit(&mut writer.lock(), &config, files, &diagnostic);
            if print_result.is_err() {
                panic!("Error printing reports")
            }
        }
    }
    pub fn error_code_to_diagnostic_code(error_code: &ReportCode) -> DiagnosticCode {
        error_code.to_string()
    }
    pub fn error(error_message: String, code: ReportCode) -> Report {
        Report::new(MessageCategory::Error, error_message, code)
    }
    pub fn warning(error_message: String, code: ReportCode) -> Report {
        Report::new(MessageCategory::Warning, error_message, code)
    }
    pub fn add_primary(
        &mut self,
        location: FileLocation,
        file_id: FileID,
        message: String,
    ) -> &mut Self {
        let label = ReportLabel::primary(file_id, location).with_message(message);
        self.get_mut_primary().push(label);
        self
    }
    pub fn add_secondary(
        &mut self,
        location: FileLocation,
        file_id: FileID,
        possible_message: Option<String>,
    ) -> &mut Self {
        let mut label = ReportLabel::secondary(file_id, location);
        if let Option::Some(message) = possible_message {
            label = label.with_message(message);
        }
        self.get_mut_secondary().push(label);
        self
    }
    pub fn add_note(&mut self, note: String) -> &mut Self {
        self.get_mut_notes().push(note);
        self
    }

    pub fn to_diagnostic(&self) -> Diagnostic<FileID> {
        let mut labels = self.get_primary().clone();
        let mut secondary = self.get_secondary().clone();
        labels.append(&mut secondary);

        if self.is_warning() { Diagnostic::warning() } else { Diagnostic::error() }
            .with_message(self.get_message())
            .with_code(Report::error_code_to_diagnostic_code(self.get_code()))
            .with_labels(labels)
            .with_notes(self.get_notes().clone())
    }

    pub fn is_error(&self) -> bool {
        self.get_category().is_error()
    }
    pub fn is_warning(&self) -> bool {
        self.get_category().is_warning()
    }
    pub fn get_category(&self) -> &MessageCategory {
        &self.category
    }
    pub fn get_message(&self) -> &String {
        &self.error_message
    }
    pub fn get_code(&self) -> &ReportCode {
        &self.error_code
    }
    pub fn get_primary(&self) -> &Vec<ReportLabel> {
        &self.primary
    }
    fn get_mut_primary(&mut self) -> &mut Vec<ReportLabel> {
        &mut self.primary
    }
    pub fn get_secondary(&self) -> &Vec<ReportLabel> {
        &self.secondary
    }
    fn get_mut_secondary(&mut self) -> &mut Vec<ReportLabel> {
        &mut self.secondary
    }
    pub fn get_notes(&self) -> &Vec<ReportNote> {
        &self.notes
    }
    fn get_mut_notes(&mut self) -> &mut Vec<ReportNote> {
        &mut self.notes
    }
}