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
// Copyright (c) ZeroC, Inc.
use crate::ast::Ast;
use crate::diagnostics::{AnnotatedDiagnostic, Diagnostics};
use crate::slice_file::SliceFile;
use crate::slice_options::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`](crate::utils::ptr_util::WeakPtr)s 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);
}
}
/// Creates an [`AnnotatedDiagnostic`] for each [`Diagnostic`](crate::diagnostics::Diagnostic) stored in this
/// `CompilationState`. This does not "use up" the diagnostics. Calling this function multiple times will yield the
/// same output.
///
/// The returned diagnostics are also de-duplicated. Duplicates are expected when slicec calls multiple plugins
/// which may run identical validation. If multiple diagnostics are _exact_ duplicates, only the first will be
/// present in the returned [`Vec`].
pub fn get_annotated_diagnostics(&self, options: &SliceOptions) -> Vec<AnnotatedDiagnostic> {
let mut annotated_diagnostics = Vec::<AnnotatedDiagnostic>::new();
for diagnostic in &*self.diagnostics {
let converted = crate::diagnostics::convert_diagnostic(diagnostic, options, &self.ast, &self.files);
if let Some(original) = annotated_diagnostics.iter_mut().find(|d| **d == converted) {
original.reported_by.extend(converted.reported_by);
} else {
annotated_diagnostics.push(converted);
}
}
annotated_diagnostics
}
}