fix lint in oxidized
[hiphop-php.git] / hphp / hack / src / oxidized / manual / errors_impl.rs
blob1f33fb4638a55a13675f5d5cdc39c1235787794b
1 // Copyright (c) Facebook, Inc. and its affiliates.
2 //
3 // This source code is licensed under the MIT license found in the
4 // LICENSE file in the "hack" directory of this source tree.
6 use std::cmp::Ordering;
8 use crate::errors::*;
9 use crate::message::Message;
10 use crate::pos::Pos;
11 use crate::pos_or_decl::PosOrDecl;
12 use crate::quickfix::Quickfix;
13 use crate::user_error::UserError;
15 impl<PP, P> UserError<PP, P> {
16     pub fn new(
17         code: ErrorCode,
18         claim: Message<PP>,
19         reasons: Vec<Message<P>>,
20         quickfixes: Vec<Quickfix>,
21     ) -> Self {
22         UserError {
23             code,
24             claim,
25             reasons,
26             quickfixes,
27         }
28     }
30     pub fn pos(&self) -> &PP {
31         let Message(pos, _msg) = &self.claim;
32         pos
33     }
35     pub fn code(&self) -> ErrorCode {
36         self.code
37     }
40 pub trait FileOrd {
41     fn cmp_file(&self, other: &Self) -> Ordering;
44 impl FileOrd for Pos {
45     fn cmp_file(&self, other: &Self) -> Ordering {
46         self.filename().cmp(other.filename())
47     }
50 impl<PP: Ord + FileOrd, P: Ord + FileOrd> Ord for UserError<PP, P> {
51     // Intended to match the implementation of `compare` in `Errors.sort` in OCaml.
52     fn cmp(&self, other: &Self) -> Ordering {
53         let Self {
54             code: self_code,
55             claim: self_claim,
56             reasons: self_reasons,
57             quickfixes: _,
58         } = self;
59         let Self {
60             code: other_code,
61             claim: other_claim,
62             reasons: other_reasons,
63             quickfixes: _,
64         } = other;
65         let Message(self_pos, self_msg) = self_claim;
66         let Message(other_pos, other_msg) = other_claim;
67         // The primary sort order is by file of the claim (main message).
68         self_pos
69             .cmp_file(other_pos)
70             // If the files are the same, sort by phase.
71             .then(((*self_code / 1000) as isize).cmp(&((*other_code / 1000) as isize)))
72             // If the phases are the same, sort by position.
73             .then(self_pos.cmp(other_pos))
74             // If the positions are the same, sort by claim message text.
75             .then(self_msg.cmp(other_msg))
76             // If the claim message text is the same, compare the reason
77             // messages (which contain further explanation for the error
78             // reported in the claim message).
79             .then(self_reasons.iter().cmp(other_reasons.iter()))
80     }
83 impl<PP: Ord + FileOrd, P: Ord + FileOrd> PartialOrd for UserError<PP, P> {
84     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
85         Some(self.cmp(other))
86     }
89 impl UserError<Pos, PosOrDecl> {
90     /// Return a struct with a `std::fmt::Display` implementation that displays
91     /// the error in the "raw" format expected by our typecheck test cases.
92     pub fn display_raw(&self) -> DisplayRaw<'_> {
93         DisplayRaw(self)
94     }
97 pub struct DisplayRaw<'a>(&'a UserError<Pos, PosOrDecl>);
99 impl<'a> std::fmt::Display for DisplayRaw<'a> {
100     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101         let UserError {
102             code,
103             claim,
104             reasons,
105             quickfixes: _,
106         } = self.0;
107         let Message(pos, msg) = claim;
108         let code = DisplayErrorCode(*code);
109         write!(f, "{}\n{} ({})", pos.string(), msg, code)?;
110         for Message(pos, msg) in reasons.iter() {
111             write!(f, "\n  {}\n  {}", pos.string(), msg)?;
112         }
113         Ok(())
114     }
117 fn error_kind(error_code: ErrorCode) -> &'static str {
118     match error_code / 1000 {
119         1 => "Parsing",
120         2 => "Naming",
121         3 => "NastCheck",
122         4 => "Typing",
123         5 => "Lint",
124         8 => "Init",
125         _ => "Other",
126     }
129 struct DisplayErrorCode(ErrorCode);
131 impl std::fmt::Display for DisplayErrorCode {
132     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
133         write!(f, "{}[{:04}]", error_kind(self.0), self.0)
134     }
137 impl Errors {
138     pub fn empty() -> Self {
139         Errors(FilesT::new(), FilesT::new())
140     }
142     pub fn is_empty(&self) -> bool {
143         let Errors(errors, _fixmes) = self;
144         errors.is_empty()
145     }
147     pub fn into_vec(self) -> Vec<Error> {
148         let Errors(errors, _fixmes) = self;
149         errors
150             .into_iter()
151             .flat_map(|(_filename, errs_by_phase)| {
152                 errs_by_phase
153                     .into_iter()
154                     .flat_map(|(_phase, errs)| errs.into_iter())
155             })
156             .collect()
157     }
159     pub fn into_sorted_vec(self) -> Vec<Error> {
160         let mut errors = self.into_vec();
161         errors.sort_unstable();
162         errors.dedup();
163         errors
164     }
167 impl Naming {
168     pub fn fd_name_already_bound(p: Pos) -> Error {
169         UserError::new(
170             Self::FdNameAlreadyBound as isize,
171             Message(p, "Field name already bound".into()),
172             vec![],
173             vec![],
174         )
175     }
177     pub fn method_needs_visibility(p: Pos) -> Error {
178         UserError::new(
179             Self::MethodNeedsVisibility as isize,
180             Message(
181                 p,
182                 "Methods need to be marked public, private, or protected.".into(),
183             ),
184             vec![],
185             vec![],
186         )
187     }
189     pub fn unsupported_trait_use_as(p: Pos) -> Error {
190         UserError::new(
191             Self::UnsupportedTraitUseAs as isize,
192             Message(
193                 p,
194                 "Trait use as is a PHP feature that is unsupported in Hack".into(),
195             ),
196             vec![],
197             vec![],
198         )
199     }
201     pub fn unsupported_instead_of(p: Pos) -> Error {
202         UserError::new(
203             Self::UnsupportedInsteadOf as isize,
204             Message(
205                 p,
206                 "insteadof is a PHP feature that is unsupported in Hack".into(),
207             ),
208             vec![],
209             vec![],
210         )
211     }
213     pub fn invalid_trait_use_as_visibility(p: Pos) -> Error {
214         UserError::new(
215             Self::InvalidTraitUseAsVisibility as isize,
216             Message(
217                 p,
218                 "Cannot redeclare trait method's visibility in this manner".into(),
219             ),
220             vec![],
221             vec![],
222         )
223     }
226 impl NastCheck {
227     pub fn not_abstract_without_typeconst(p: Pos) -> Error {
228         UserError::new(
229             Self::NotAbstractWithoutTypeconst as isize,
230             Message(
231                 p,
232                 "This type constant is not declared as abstract, it must have an assigned type"
233                     .into(),
234             ),
235             vec![],
236             vec![],
237         )
238     }
240     pub fn multiple_xhp_category(p: Pos) -> Error {
241         UserError::new(
242             Self::MultipleXhpCategory as isize,
243             Message(
244                 p,
245                 "XHP classes can only contain one category declaration".into(),
246             ),
247             vec![],
248             vec![],
249         )
250     }
252     pub fn partially_abstract_typeconst_definition(p: Pos) -> Error {
253         UserError::new(
254             Self::PartiallyAbstractTypeconstDefinition as isize,
255             Message(
256                 p,
257                 "`as` constraints are only legal on abstract type constants".into(),
258             ),
259             vec![],
260             vec![],
261         )
262     }