| 1 | use fluent_syntax::ast::InlineExpression; |
| 2 | use std::error::Error; |
| 3 | |
| 4 | /// Maps an [`InlineExpression`] into the kind of reference, with owned strings |
| 5 | /// that identify the expression. This makes it so that the [`InlineExpression`] can |
| 6 | /// be used to generate an error string. |
| 7 | #[derive (Debug, PartialEq, Eq, Clone)] |
| 8 | pub enum ReferenceKind { |
| 9 | Function { |
| 10 | id: String, |
| 11 | }, |
| 12 | Message { |
| 13 | id: String, |
| 14 | attribute: Option<String>, |
| 15 | }, |
| 16 | Term { |
| 17 | id: String, |
| 18 | attribute: Option<String>, |
| 19 | }, |
| 20 | Variable { |
| 21 | id: String, |
| 22 | }, |
| 23 | } |
| 24 | |
| 25 | impl<T> From<&InlineExpression<T>> for ReferenceKind |
| 26 | where |
| 27 | T: ToString, |
| 28 | { |
| 29 | fn from(exp: &InlineExpression<T>) -> Self { |
| 30 | match exp { |
| 31 | InlineExpression::FunctionReference { id: &Identifier, .. } => Self::Function { |
| 32 | id: id.name.to_string(), |
| 33 | }, |
| 34 | InlineExpression::MessageReference { id: &Identifier, attribute: &Option> } => Self::Message { |
| 35 | id: id.name.to_string(), |
| 36 | attribute: attribute.as_ref().map(|i: &Identifier| i.name.to_string()), |
| 37 | }, |
| 38 | InlineExpression::TermReference { id: &Identifier, attribute: &Option>, .. } => Self::Term { |
| 39 | id: id.name.to_string(), |
| 40 | attribute: attribute.as_ref().map(|i: &Identifier| i.name.to_string()), |
| 41 | }, |
| 42 | InlineExpression::VariableReference { id: &Identifier, .. } => Self::Variable { |
| 43 | id: id.name.to_string(), |
| 44 | }, |
| 45 | _ => unreachable!(), |
| 46 | } |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | /// Errors generated during the process of resolving a fluent message into a string. |
| 51 | /// This process takes place in the `write` method of the `WriteValue` trait. |
| 52 | #[derive (Debug, PartialEq, Eq, Clone)] |
| 53 | pub enum ResolverError { |
| 54 | Reference(ReferenceKind), |
| 55 | NoValue(String), |
| 56 | MissingDefault, |
| 57 | Cyclic, |
| 58 | TooManyPlaceables, |
| 59 | } |
| 60 | |
| 61 | impl std::fmt::Display for ResolverError { |
| 62 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 63 | match self { |
| 64 | Self::Reference(exp) => match exp { |
| 65 | ReferenceKind::Function { id } => write!(f, "Unknown function: {}()" , id), |
| 66 | ReferenceKind::Message { |
| 67 | id, |
| 68 | attribute: None, |
| 69 | } => write!(f, "Unknown message: {}" , id), |
| 70 | ReferenceKind::Message { |
| 71 | id, |
| 72 | attribute: Some(attribute), |
| 73 | } => write!(f, "Unknown attribute: {}. {}" , id, attribute), |
| 74 | ReferenceKind::Term { |
| 75 | id, |
| 76 | attribute: None, |
| 77 | } => write!(f, "Unknown term: - {}" , id), |
| 78 | ReferenceKind::Term { |
| 79 | id, |
| 80 | attribute: Some(attribute), |
| 81 | } => write!(f, "Unknown attribute: - {}. {}" , id, attribute), |
| 82 | ReferenceKind::Variable { id } => write!(f, "Unknown variable: $ {}" , id), |
| 83 | }, |
| 84 | Self::NoValue(id) => write!(f, "No value: {}" , id), |
| 85 | Self::MissingDefault => f.write_str("No default" ), |
| 86 | Self::Cyclic => f.write_str("Cyclical dependency detected" ), |
| 87 | Self::TooManyPlaceables => f.write_str("Too many placeables" ), |
| 88 | } |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | impl<T> From<&InlineExpression<T>> for ResolverError |
| 93 | where |
| 94 | T: ToString, |
| 95 | { |
| 96 | fn from(exp: &InlineExpression<T>) -> Self { |
| 97 | Self::Reference(exp.into()) |
| 98 | } |
| 99 | } |
| 100 | |
| 101 | impl Error for ResolverError {} |
| 102 | |