1 // Copyright (c) Facebook, Inc. and its affiliates.
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
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)]
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>,
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(
62 .map(|(name, decl)| (name, decl, Int64(hh_hash::hash(&decl) as i64))),
64 ParsedFileWithHashes {
65 mode: parsed_file.mode,
66 hash: file_decls_hash,
72 // NB: Must keep in sync with OCaml type Direct_decl_parser.decls
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> {}
97 pub const fn empty() -> Self {
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 {
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)
115 pub fn rev<A: arena_trait::Arena>(&mut self, arena: &'a A) {
116 self.0 = self.0.rev(arena)
119 pub fn iter(&self) -> impl Iterator<Item = (&'a str, Decl<'a>)> {
120 self.0.iter().copied()
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)),
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)),
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)),
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)),
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,
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)),
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()
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()
180 pub fn kind(&self) -> NameType {
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,
190 pub fn dep_type(&self) -> typing_deps_hash::DepType {
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,
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")