ressa_r/
error.rs

1use ress::{tokens::Keyword, Position};
2use std::fmt::{Display, Formatter, Result};
3#[derive(Debug)]
4pub enum Error {
5    UnexpectedEoF,
6    ParseAfterEoF,
7    RestrictedIdent(Position),
8    UnexpectedToken(Position, String),
9    UnableToReinterpret(Position, String, String),
10    Redecl(Position, String),
11    OperationError(Position, String),
12    InvalidGetterParams(Position),
13    InvalidSetterParams(Position),
14    NonStrictFeatureInStrictContext(Position, String),
15    InvalidImportError(Position),
16    InvalidExportError(Position),
17    InvalidYield(Position),
18    InvalidUseOfContextualKeyword(Position, String),
19    TryWithNoCatchOrFinally(Position),
20    InvalidCatchArg(Position),
21    ThrowWithNoArg(Position),
22    UnknownOptionalLabel(Position, Keyword<()>, String),
23    InvalidOptionalLabel(Position),
24    UseOfModuleFeatureOutsideOfModule(Position, String),
25    NewLineAfterFatArrow(Position),
26    StrictModeArgumentsOrEval(Position),
27    InvalidSuper(Position),
28    InvalidFuncPosition(Position, String),
29    InvalidClassPosition(Position, String),
30    ForOfInAssign(Position, String),
31    ContinueOutsideOfIteration(Position),
32    InvalidParameter(Position, String),
33    OctalLiteral(Position),
34    HtmlCommentInModule(Position),
35    InvalidRegEx(Position, String),
36    InvalidTrailingComma(Position),
37    InvalidEscape(Position, String),
38    LexicalRedecl(Position, Position, String),
39    InvalidLHS(Position),
40    ForOfNotSimple(Position),
41    InvalidStartOfExpressionStmt(Position, String),
42    DuplicateExport(Position, String),
43    UndefinedExports(Vec<String>),
44    ContinueOfNotIterationLabel(Position, String),
45    Scanner(ress::error::Error),
46    Regex(res_regex::Error),
47    Io(std::io::Error),
48    Misc(String),
49}
50
51impl Display for Error {
52    fn fmt(&self, f: &mut Formatter) -> Result {
53        match self {
54            Error::UnexpectedToken(ref pos, ref msg) => write!(f, "Unexpected Token at {}: {}", pos, msg),
55            Error::UnexpectedEoF => write!(f, "Unexpectedly found the end of the file"),
56            Error::ParseAfterEoF => write!(f, "Parser attempted to get the next token after finding the end of the file"),
57            Error::RestrictedIdent(pos) => write!(f, "Restricted word used as identifier at {}", pos),
58            Error::UnableToReinterpret(ref pos, ref from, ref to) => write!(f, "Unable to re-interpret from {} to {} at {}", from, to, pos),
59            Error::Redecl(ref pos, ref ident) => write!(f, "Nested label at {} shadows parent: {}", pos, ident),
60            Error::OperationError(ref pos, ref msg) => write!(f, "Invalid operation, {}: {}", pos, msg),
61            Error::InvalidGetterParams(ref pos) => write!(f, "Found a getter method that takes arguments at {}, getter methods cannot take arguments", pos),
62            Error::InvalidSetterParams(ref pos) => write!(f, "Found a setter method that takes more or less than 1 argument at {}, setter methods must take only one argument", pos),
63            Error::InvalidYield(ref pos) => write!(f, "Yield cannot be used as an identifier at {}", pos),
64            Error::NonStrictFeatureInStrictContext(ref pos, ref name) => write!(f, "Attempting to use non-strict feature {} in a strict context at {}", name, pos),
65            Error::InvalidImportError(ref pos) => write!(f, "Inavlid use of es6 import syntax at {}", pos),
66            Error::InvalidExportError(ref pos) => write!(f, "Inavlid use of es6 export syntax at {}", pos),
67            Error::InvalidUseOfContextualKeyword(ref pos, ref ident) => write!(f, "Inavlid use of contextual keyword {} at {}", pos, ident),
68            Error::TryWithNoCatchOrFinally(ref pos) => write!(f, "Try catch block must have catch or finally clause at {}", pos),
69            Error::InvalidCatchArg(ref pos) => write!(f, "Inavlid parameter in catch block at {}", pos),
70            Error::ThrowWithNoArg(ref pos) => write!(f, "Throw statements without an argument {}", pos),
71            Error::UnknownOptionalLabel(ref pos, ref key, ref label) => write!(f, "Attempt to {0} {1} but {1} is unknown in this scope at {2}", key.to_string(), label, pos),
72            Error::InvalidOptionalLabel(ref pos) => write!(f, "Attempt to break with no label is not allowed unless in an iteration or switch: {}", pos),
73            Error::UseOfModuleFeatureOutsideOfModule(ref pos, ref feature) => write!(f, "Used {} at {} which is only available inside of an es6 module", feature, pos),
74            Error::NewLineAfterFatArrow(ref pos) => write!(f, "New line after fat arrow at {}", pos),
75            Error::StrictModeArgumentsOrEval(ref pos) => write!(f, "arguments or eval used as an identifier in strict mode near {}", pos),
76            Error::InvalidFuncPosition(ref pos, ref msg) => write!(f, "{} at {}", msg, pos),
77            Error::InvalidClassPosition(ref pos, ref msg) => write!(f, "{} at {}", msg, pos),
78            Error::ForOfInAssign(ref pos, ref msg) => write!(f, "{} at {}", msg, pos),
79            Error::InvalidSuper(ref pos) => write!(f, "Invalid use of super at {}", pos),
80            Error::ContinueOutsideOfIteration(ref pos) => write!(f, "Invalid use of continue at {}", pos),
81            Error::InvalidParameter(ref pos, ref msg) => write!(f, "Invalid paramter at {} -- {}", pos, msg),
82            Error::OctalLiteral(ref pos) => write!(f, "Invalid use of octal literal at {}", pos),
83            Error::HtmlCommentInModule(ref pos) => write!(f, "HTML Comments are not available in module code: {}", pos),
84            Error::InvalidRegEx(ref pos, ref msg) => write!(f, "Invalid regular expression literal at {} -- {}", pos, msg),
85            Error::InvalidTrailingComma(ref pos) => write!(f, "Invalid trailing comma at {}", pos),
86            Error::InvalidEscape(ref pos, ref msg) => write!(f, "{} at {}", msg, pos),
87            Error::LexicalRedecl(ref orig, ref redecl, ref id) => write!(f, "identifier {} was previously declared at {} and again at {}", id, orig, redecl),
88            Error::InvalidLHS(ref pos) => write!(f, "invalid left hand side at {}", pos),
89            Error::ForOfNotSimple(ref pos) => write!(f, "initializer of a for-of loop must be a simple assignment target {}", pos),
90            Error::InvalidStartOfExpressionStmt(ref pos, ref token) => write!(f, "Expression statement cannot start with {} at {}", token, pos),
91            Error::DuplicateExport(ref pos, ref token) => write!(f, "Found duplicate export with name {} at {}", token, pos),
92            Error::UndefinedExports(ref names) => write!(f, "Undefined exports in module: {}", names.join(", ")),
93            Error::ContinueOfNotIterationLabel(ref pos, ref token) => write!(f, "Label `{}` is does not label a loop, continue is invalid at {}", token, pos),
94            Error::Scanner(ref e) => write!(f, "Error when tokenizing {}", e),
95            Error::Regex(ref e) => write!(f, "{}", e),
96            Error::Io(ref e) => write!(f, "{}", e),
97            Error::Misc(ref e) => write!(f, "{}", e),
98        }
99    }
100}
101
102impl Error {
103    pub fn unable_to_reinterpret(pos: Position, from: &str, to: &str) -> Self {
104        Error::UnableToReinterpret(pos, from.to_owned(), to.to_owned())
105    }
106
107    pub fn position(&self) -> Option<Position> {
108        use self::Error::*;
109        match self {
110            RestrictedIdent(p) => Some(*p),
111            UnexpectedToken(p, _) => Some(*p),
112            UnableToReinterpret(p, _, _) => Some(*p),
113            Redecl(p, _) => Some(*p),
114            OperationError(p, _) => Some(*p),
115            InvalidGetterParams(p) => Some(*p),
116            InvalidSetterParams(p) => Some(*p),
117            NonStrictFeatureInStrictContext(p, _) => Some(*p),
118            InvalidImportError(p) => Some(*p),
119            InvalidExportError(p) => Some(*p),
120            InvalidYield(p) => Some(*p),
121            InvalidUseOfContextualKeyword(p, _) => Some(*p),
122            TryWithNoCatchOrFinally(p) => Some(*p),
123            InvalidCatchArg(p) => Some(*p),
124            ThrowWithNoArg(p) => Some(*p),
125            UnknownOptionalLabel(p, _, _) => Some(*p),
126            InvalidOptionalLabel(p) => Some(*p),
127            UseOfModuleFeatureOutsideOfModule(p, _) => Some(*p),
128            NewLineAfterFatArrow(p) => Some(*p),
129            StrictModeArgumentsOrEval(p) => Some(*p),
130            InvalidSuper(p) => Some(*p),
131            InvalidFuncPosition(p, _) => Some(*p),
132            InvalidClassPosition(p, _) => Some(*p),
133            ForOfInAssign(p, _) => Some(*p),
134            ContinueOutsideOfIteration(p) => Some(*p),
135            InvalidParameter(p, _) => Some(*p),
136            OctalLiteral(p) => Some(*p),
137            HtmlCommentInModule(p) => Some(*p),
138            InvalidRegEx(p, _) => Some(*p),
139            InvalidTrailingComma(p) => Some(*p),
140            InvalidEscape(p, _) => Some(*p),
141            LexicalRedecl(p, _, _) => Some(*p),
142            InvalidLHS(p) => Some(*p),
143            ForOfNotSimple(p) => Some(*p),
144            InvalidStartOfExpressionStmt(p, _) => Some(*p),
145            DuplicateExport(p, _) => Some(*p),
146            ContinueOfNotIterationLabel(p, _) => Some(*p),
147            Scanner(e) => Some(Position {
148                line: e.line,
149                column: e.column,
150            }),
151            _ => None,
152        }
153    }
154}
155
156impl From<::std::io::Error> for Error {
157    fn from(other: ::std::io::Error) -> Self {
158        Error::Io(other)
159    }
160}
161impl ::std::error::Error for Error {}
162
163impl From<ress::error::Error> for Error {
164    fn from(other: ress::error::Error) -> Self {
165        Error::Scanner(other)
166    }
167}
168
169impl From<res_regex::Error> for Error {
170    fn from(value: res_regex::Error) -> Self {
171        Self::Regex(value)
172    }
173}
174
175#[cfg(test)]
176mod tests {
177    use super::*;
178
179    #[test]
180    fn error_is_send_and_sync() {
181        fn print_error<E>(arg: E)
182        where
183            E: std::error::Error + Send + Sync,
184        {
185            println!("{arg}");
186        }
187        print_error(Error::Misc("some misc error".to_string()))
188    }
189}