driveby tweak: use Decl to filter types instead of NameType
[hiphop-php.git] / hphp / hack / src / oxidized_by_ref / manual / direct_decl_parser.rs
blobd1202f59a1ad42bab1f331a14f44a2a3b7bb23b5
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 serde::{Deserialize, Serialize};
8 use arena_collections::List;
9 use arena_trait::TrivialDrop;
10 use no_pos_hash::NoPosHash;
11 use ocamlrep::slab::OwnedSlab;
12 use ocamlrep_caml_builtins::Int64;
13 use ocamlrep_derive::{FromOcamlRepIn, ToOcamlRep};
14 use oxidized::file_info::NameType;
16 use crate::{file_info, shallow_decl_defs, typing_defs};
18 pub use shallow_decl_defs::Decl;
20 // NB: Must keep in sync with OCaml type Direct_decl_parser.parsed_file
21 #[derive(
22     Copy,
23     Clone,
24     Deserialize,
25     Eq,
26     FromOcamlRepIn,
27     Hash,
28     NoPosHash,
29     Ord,
30     PartialEq,
31     PartialOrd,
32     Serialize,
33     ToOcamlRep
35 pub struct ParsedFile<'a> {
36     pub mode: Option<file_info::Mode>,
37     #[serde(deserialize_with = "arena_deserializer::arena", borrow)]
38     pub file_attributes: &'a [&'a typing_defs::UserAttribute<'a>],
39     #[serde(deserialize_with = "arena_deserializer::arena", borrow)]
40     pub decls: Decls<'a>,
41     /// True if the FFP detected parse errors while parsing. Other parse errors
42     /// are detected in a second pass over the CST, and this field does not
43     /// indicate whether errors would be detected in that second pass.
44     pub has_first_pass_parse_errors: bool,
47 // NB: Must keep in sync with OCaml type `Direct_decl_parser.parsed_file_with_hashes`
48 #[derive(ocamlrep_derive::ToOcamlRep)]
49 pub struct ParsedFileWithHashes<'a> {
50     pub mode: Option<file_info::Mode>,
51     pub hash: Int64,
52     pub decls: Vec<(&'a str, Decl<'a>, Int64)>,
55 impl<'a> From<ParsedFile<'a>> for ParsedFileWithHashes<'a> {
56     fn from(parsed_file: ParsedFile<'a>) -> ParsedFileWithHashes<'a> {
57         let file_decls_hash = Int64(hh_hash::position_insensitive_hash(&parsed_file.decls) as i64);
58         let decls = Vec::from_iter(
59             parsed_file
60                 .decls
61                 .into_iter()
62                 .map(|(name, decl)| (name, decl, Int64(hh_hash::hash(&decl) as i64))),
63         );
64         ParsedFileWithHashes {
65             mode: parsed_file.mode,
66             hash: file_decls_hash,
67             decls,
68         }
69     }
72 // NB: Must keep in sync with OCaml type Direct_decl_parser.decls
73 #[derive(
74     Copy,
75     Clone,
76     Deserialize,
77     Eq,
78     FromOcamlRepIn,
79     Hash,
80     NoPosHash,
81     Ord,
82     PartialEq,
83     PartialOrd,
84     Serialize,
85     ToOcamlRep
87 pub struct Decls<'a>(
88     #[serde(deserialize_with = "arena_deserializer::arena", borrow)]
89     pub  List<'a, (&'a str, Decl<'a>)>,
92 arena_deserializer::impl_deserialize_in_arena!(Decls<'arena>);
94 impl<'a> TrivialDrop for Decls<'a> {}
96 impl<'a> Decls<'a> {
97     pub const fn empty() -> Self {
98         Self(List::empty())
99     }
101     pub fn get(&self, kind: NameType, symbol: &str) -> Option<Decl<'a>> {
102         self.iter().find_map(|(name, decl)| {
103             if decl.kind() == kind && name == symbol {
104                 Some(decl)
105             } else {
106                 None
107             }
108         })
109     }
111     pub fn add<A: arena_trait::Arena>(&mut self, name: &'a str, decl: Decl<'a>, arena: &'a A) {
112         self.0.push_front((name, decl), arena)
113     }
115     pub fn rev<A: arena_trait::Arena>(&mut self, arena: &'a A) {
116         self.0 = self.0.rev(arena)
117     }
119     pub fn iter(&self) -> impl Iterator<Item = (&'a str, Decl<'a>)> {
120         self.0.iter().copied()
121     }
123     pub fn classes(
124         &self,
125     ) -> impl Iterator<Item = (&'a str, &'a shallow_decl_defs::ShallowClass<'a>)> {
126         self.iter().filter_map(|(name, decl)| match decl {
127             Decl::Class(decl) => Some((name, decl)),
128             _ => None,
129         })
130     }
131     pub fn funs(&self) -> impl Iterator<Item = (&'a str, &'a typing_defs::FunElt<'a>)> {
132         self.iter().filter_map(|(name, decl)| match decl {
133             Decl::Fun(decl) => Some((name, decl)),
134             _ => None,
135         })
136     }
137     pub fn typedefs(&self) -> impl Iterator<Item = (&'a str, &'a typing_defs::TypedefType<'a>)> {
138         self.iter().filter_map(|(name, decl)| match decl {
139             Decl::Typedef(decl) => Some((name, decl)),
140             _ => None,
141         })
142     }
143     pub fn consts(&self) -> impl Iterator<Item = (&'a str, &'a typing_defs::ConstDecl<'a>)> {
144         self.iter().filter_map(|(name, decl)| match decl {
145             Decl::Const(decl) => Some((name, decl)),
146             _ => None,
147         })
148     }
149     pub fn types(&self) -> impl Iterator<Item = (&'a str, Decl<'a>)> {
150         self.iter().filter(|(_, decl)| match decl {
151             Decl::Class(_) | Decl::Typedef(_) => true,
152             Decl::Fun(_) | Decl::Const(_) | Decl::Module(_) => false,
153         })
154     }
156     pub fn modules(&self) -> impl Iterator<Item = (&'a str, &'a typing_defs::ModuleDefType<'a>)> {
157         self.iter().filter_map(|(name, decl)| match decl {
158             Decl::Module(decl) => Some((name, decl)),
159             _ => None,
160         })
161     }
164 impl<'a> IntoIterator for Decls<'a> {
165     type Item = (&'a str, Decl<'a>);
166     type IntoIter = std::iter::Copied<arena_collections::list::Iter<'a, (&'a str, Decl<'a>)>>;
168     fn into_iter(self) -> Self::IntoIter {
169         self.0.iter().copied()
170     }
173 impl std::fmt::Debug for Decls<'_> {
174     fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
175         fmt.debug_map().entries(self.iter()).finish()
176     }
179 impl<'a> Decl<'a> {
180     pub fn kind(&self) -> NameType {
181         match self {
182             Decl::Class(..) => NameType::Class,
183             Decl::Fun(..) => NameType::Fun,
184             Decl::Typedef(..) => NameType::Typedef,
185             Decl::Const(..) => NameType::Const,
186             Decl::Module(..) => NameType::Module,
187         }
188     }
190     pub fn dep_type(&self) -> typing_deps_hash::DepType {
191         match self {
192             Decl::Fun(..) => typing_deps_hash::DepType::Fun,
193             Decl::Const(..) => typing_deps_hash::DepType::GConst,
194             Decl::Class(..) | Decl::Typedef(..) => typing_deps_hash::DepType::Type,
195             Decl::Module(..) => typing_deps_hash::DepType::Module,
196         }
197     }
199     pub fn to_slab(&self) -> OwnedSlab {
200         ocamlrep::slab::to_slab(self)
201             .expect("Got immediate value, but Decl should always convert to a block value")
202     }