1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// Copyright (c) ZeroC, Inc.
use crate::ast::Ast;
use crate::diagnostic_emitter::{emit_totals, DiagnosticEmitter};
use crate::diagnostics::{get_totals, Diagnostic, Diagnostics};
use crate::slice_file::SliceFile;
use crate::slice_options::{DiagnosticFormat, SliceOptions};
#[derive(Debug, Default)]
pub struct CompilationState {
pub ast: Ast,
pub diagnostics: Diagnostics,
pub files: Vec<SliceFile>,
}
impl CompilationState {
pub fn create() -> Self {
CompilationState {
ast: Ast::create(),
diagnostics: Diagnostics::new(),
files: Vec::new(),
}
}
/// Calls the provided function on this `CompilationState` if and only if no errors have been reported so far.
/// If any errors are present in this `CompilationState`'s [Diagnostics] container, this is no-op.
pub fn apply(&mut self, function: fn(&mut Self)) {
if !self.diagnostics.has_errors() {
function(self);
}
}
/// Calls the provided function on this `CompilationState` if and only if no errors have been reported so far.
/// If any errors are present in this `CompilationState`'s [Diagnostics] container, this is no-op.
///
/// # Safety
///
/// The caller of this function must ensure that no (`WeakPtr`s)[crate::utils::ptr_util::WeakPtr] exist that point
/// to the contents of this `CompilationState`. Even if they're not being actively used, their existence causes UB.
pub unsafe fn apply_unsafe(&mut self, function: unsafe fn(&mut Self)) {
if !self.diagnostics.has_errors() {
function(self);
}
}
/// This function is the exit point of the compiler.
/// It emits diagnostics to the console, along with the total number of warning/errors emitted.
/// After this it returns whether any errors were emitted.
pub fn emit_diagnostics(self, options: &SliceOptions) -> bool {
let diagnostics = self.diagnostics.into_updated(&self.ast, &self.files, options);
let (total_warnings, total_errors) = get_totals(&diagnostics);
// Print any diagnostics to the console, along with the total number of warnings and errors emitted.
let mut stderr = console::Term::stderr();
let mut emitter = DiagnosticEmitter::new(&mut stderr, options, &self.files);
DiagnosticEmitter::emit_diagnostics(&mut emitter, diagnostics).expect("failed to emit diagnostics");
// Only emit the summary message if we're writing human-readable output.
if options.diagnostic_format == DiagnosticFormat::Human {
emit_totals(total_warnings, total_errors).expect("failed to emit totals");
}
total_errors != 0
}
/// Consumes this `CompilationState` and returns the diagnostics it contains.
/// This method exists to simplify the testing of diagnostic emission.
pub fn into_diagnostics(self, options: &SliceOptions) -> Vec<Diagnostic> {
self.diagnostics.into_updated(&self.ast, &self.files, options)
}
}