rustc_errors/
error.rs

1use std::borrow::Cow;
2use std::error::Error;
3use std::fmt;
4
5use rustc_error_messages::fluent_bundle::resolver::errors::{ReferenceKind, ResolverError};
6use rustc_error_messages::{FluentArgs, FluentError};
7
8#[derive(Debug)]
9pub enum TranslateError<'args> {
10    One {
11        id: &'args Cow<'args, str>,
12        args: &'args FluentArgs<'args>,
13        kind: TranslateErrorKind<'args>,
14    },
15    Two {
16        primary: Box<TranslateError<'args>>,
17        fallback: Box<TranslateError<'args>>,
18    },
19}
20
21impl<'args> TranslateError<'args> {
22    pub fn message(id: &'args Cow<'args, str>, args: &'args FluentArgs<'args>) -> Self {
23        Self::One { id, args, kind: TranslateErrorKind::MessageMissing }
24    }
25
26    pub fn primary(id: &'args Cow<'args, str>, args: &'args FluentArgs<'args>) -> Self {
27        Self::One { id, args, kind: TranslateErrorKind::PrimaryBundleMissing }
28    }
29
30    pub fn attribute(
31        id: &'args Cow<'args, str>,
32        args: &'args FluentArgs<'args>,
33        attr: &'args str,
34    ) -> Self {
35        Self::One { id, args, kind: TranslateErrorKind::AttributeMissing { attr } }
36    }
37
38    pub fn value(id: &'args Cow<'args, str>, args: &'args FluentArgs<'args>) -> Self {
39        Self::One { id, args, kind: TranslateErrorKind::ValueMissing }
40    }
41
42    pub fn fluent(
43        id: &'args Cow<'args, str>,
44        args: &'args FluentArgs<'args>,
45        errs: Vec<FluentError>,
46    ) -> Self {
47        Self::One { id, args, kind: TranslateErrorKind::Fluent { errs } }
48    }
49
50    pub fn and(self, fallback: TranslateError<'args>) -> TranslateError<'args> {
51        Self::Two { primary: Box::new(self), fallback: Box::new(fallback) }
52    }
53}
54
55#[derive(Debug)]
56pub enum TranslateErrorKind<'args> {
57    MessageMissing,
58    PrimaryBundleMissing,
59    AttributeMissing { attr: &'args str },
60    ValueMissing,
61    Fluent { errs: Vec<FluentError> },
62}
63
64impl fmt::Display for TranslateError<'_> {
65    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66        use TranslateErrorKind::*;
67
68        match self {
69            Self::One { id, args, kind } => {
70                writeln!(f, "failed while formatting fluent string `{id}`: ")?;
71                match kind {
72                    MessageMissing => writeln!(f, "message was missing")?,
73                    PrimaryBundleMissing => writeln!(f, "the primary bundle was missing")?,
74                    AttributeMissing { attr } => {
75                        writeln!(f, "the attribute `{attr}` was missing")?;
76                        writeln!(f, "help: add `.{attr} = <message>`")?;
77                    }
78                    ValueMissing => writeln!(f, "the value was missing")?,
79                    Fluent { errs } => {
80                        for err in errs {
81                            match err {
82                                FluentError::ResolverError(ResolverError::Reference(
83                                    ReferenceKind::Message { id, .. }
84                                    | ReferenceKind::Variable { id, .. },
85                                )) => {
86                                    if args.iter().any(|(arg_id, _)| arg_id == id) {
87                                        writeln!(
88                                            f,
89                                            "argument `{id}` exists but was not referenced correctly"
90                                        )?;
91                                        writeln!(f, "help: try using `{{${id}}}` instead")?;
92                                    } else {
93                                        writeln!(
94                                            f,
95                                            "the fluent string has an argument `{id}` that was not found."
96                                        )?;
97                                        let vars: Vec<&str> =
98                                            args.iter().map(|(a, _v)| a).collect();
99                                        match &*vars {
100                                            [] => writeln!(f, "help: no arguments are available")?,
101                                            [one] => writeln!(
102                                                f,
103                                                "help: the argument `{one}` is available"
104                                            )?,
105                                            [first, middle @ .., last] => {
106                                                write!(f, "help: the arguments `{first}`")?;
107                                                for a in middle {
108                                                    write!(f, ", `{a}`")?;
109                                                }
110                                                writeln!(f, " and `{last}` are available")?;
111                                            }
112                                        }
113                                    }
114                                }
115                                _ => writeln!(f, "{err}")?,
116                            }
117                        }
118                    }
119                }
120            }
121            // If someone cares about primary bundles, they'll probably notice it's missing
122            // regardless or will be using `debug_assertions`
123            // so we skip the arm below this one to avoid confusing the regular user.
124            Self::Two { primary: box Self::One { kind: PrimaryBundleMissing, .. }, fallback } => {
125                fmt::Display::fmt(fallback, f)?;
126            }
127            Self::Two { primary, fallback } => {
128                writeln!(
129                    f,
130                    "first, fluent formatting using the primary bundle failed:\n {primary}\n \
131                    while attempting to recover by using the fallback bundle instead, another error occurred:\n{fallback}"
132                )?;
133            }
134        }
135        Ok(())
136    }
137}
138
139impl Error for TranslateError<'_> {}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy