Skip to main content

codex_execpolicy/
error.rs

1use starlark::Error as StarlarkError;
2use thiserror::Error;
3
4pub type Result<T> = std::result::Result<T, Error>;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub struct TextPosition {
8    pub line: usize,
9    pub column: usize,
10}
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub struct TextRange {
14    pub start: TextPosition,
15    pub end: TextPosition,
16}
17
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct ErrorLocation {
20    pub path: String,
21    pub range: TextRange,
22}
23
24#[derive(Debug, Error)]
25pub enum Error {
26    #[error("invalid decision: {0}")]
27    InvalidDecision(String),
28    #[error("invalid pattern element: {0}")]
29    InvalidPattern(String),
30    #[error("invalid example: {0}")]
31    InvalidExample(String),
32    #[error("invalid rule: {0}")]
33    InvalidRule(String),
34    #[error(
35        "expected every example to match at least one rule. rules: {rules:?}; unmatched examples: \
36         {examples:?}"
37    )]
38    ExampleDidNotMatch {
39        rules: Vec<String>,
40        examples: Vec<String>,
41        location: Option<ErrorLocation>,
42    },
43    #[error("expected example to not match rule `{rule}`: {example}")]
44    ExampleDidMatch {
45        rule: String,
46        example: String,
47        location: Option<ErrorLocation>,
48    },
49    #[error("starlark error: {0}")]
50    Starlark(StarlarkError),
51}
52
53impl Error {
54    pub fn with_location(self, location: ErrorLocation) -> Self {
55        match self {
56            Error::ExampleDidNotMatch {
57                rules,
58                examples,
59                location: None,
60            } => Error::ExampleDidNotMatch {
61                rules,
62                examples,
63                location: Some(location),
64            },
65            Error::ExampleDidMatch {
66                rule,
67                example,
68                location: None,
69            } => Error::ExampleDidMatch {
70                rule,
71                example,
72                location: Some(location),
73            },
74            other => other,
75        }
76    }
77
78    pub fn location(&self) -> Option<ErrorLocation> {
79        match self {
80            Error::ExampleDidNotMatch { location, .. }
81            | Error::ExampleDidMatch { location, .. } => location.clone(),
82            Error::Starlark(err) => err.span().map(|span| {
83                let resolved = span.resolve_span();
84                ErrorLocation {
85                    path: span.filename().to_string(),
86                    range: TextRange {
87                        start: TextPosition {
88                            line: resolved.begin.line + 1,
89                            column: resolved.begin.column + 1,
90                        },
91                        end: TextPosition {
92                            line: resolved.end.line + 1,
93                            column: resolved.end.column + 1,
94                        },
95                    },
96                }
97            }),
98            _ => None,
99        }
100    }
101}