2 * Copyright (c) 2015, Facebook, Inc.
5 * This source code is licensed under the MIT license found in the
6 * LICENSE file in the "hack" directory of this source tree.
10 (*****************************************************************************)
11 (* This module defines the data structured used to describe the content of
13 * The parser constructs FileInfo.t structs, that contain names and positions
14 * plus some extra info required for the build.
15 * After the names have been checked (Naming.make_env), we "simplify" the
16 * struct and only keep the names defined in the files we know about.
18 (*****************************************************************************)
23 (*****************************************************************************)
25 (*****************************************************************************)
28 | Mhhi
(** just declare signatures, don't check anything *)
29 | Mstrict
(** check everything! *)
30 | Mpartial
(** Don't fail if you see a function/class you don't know *)
31 [@@deriving eq
, show
, enum
]
33 let parse_mode = function
37 | "partial" -> Some Mpartial
40 let is_strict = function
46 let string_of_mode = function
49 | Mpartial
-> "partial"
51 let pp_mode fmt mode
=
52 Format.pp_print_string fmt
56 | Mstrict
-> "Mstrict"
57 | Mpartial
-> "Mpartial"
59 (*****************************************************************************)
60 (* Positions of names in a file *)
61 (*****************************************************************************)
66 | RecordDef
[@value 2]
69 [@@deriving eq
, show
, enum
, ord
]
71 (** We define two types of positions establishing the location of a given name:
72 * a Full position contains the exact position of a name in a file, and a
73 * File position contains just the file and the type of toplevel entity,
74 * allowing us to lazily retrieve the name's exact location if necessary.
78 | File
of name_type
* Relative_path.t
81 type id
= pos
* string [@@deriving eq
, show
]
83 (*****************************************************************************)
84 (* The record produced by the parsing phase. *)
85 (*****************************************************************************)
87 type hash_type
= Int64.t
option [@@deriving eq
]
89 let pp_hash_type fmt hash
=
91 | None
-> Format.fprintf fmt
"None"
92 | Some hash
-> Format.fprintf fmt
"Some (%s)" (Int64.to_string hash
)
94 (** The record produced by the parsing phase. *)
97 file_mode
: mode
option;
100 record_defs
: id list
;
103 comments
: (Pos.t
* comment
) list
option;
104 (** None if loaded from saved state *)
120 let pos_full (p
, name
) = (Full p
, name
)
122 let get_pos_filename = function
123 | Full p
-> Pos.filename p
126 (*****************************************************************************)
127 (* The simplified record used after parsing. *)
128 (*****************************************************************************)
130 (** The simplified record used after parsing. *)
134 n_record_defs
: SSet.t
;
139 (** The simplified record stored in saved-state.*)
143 sn_record_defs
: SSet.t
;
148 (** Data structure stored in the saved state *)
150 s_names
: saved_names
;
151 s_hash
: Int64.t
option;
158 n_classes
= SSet.empty
;
159 n_record_defs
= SSet.empty
;
160 n_types
= SSet.empty
;
161 n_consts
= SSet.empty
;
164 (*****************************************************************************)
165 (* Functions simplifying the file information. *)
166 (*****************************************************************************)
168 let name_set_of_idl idl
=
169 List.fold_left idl ~f
:(fun acc
(_
, x
) -> SSet.add x acc
) ~init
:SSet.empty
184 let n_funs = name_set_of_idl funs
in
185 let n_classes = name_set_of_idl classes
in
186 let n_record_defs = name_set_of_idl record_defs
in
187 let n_types = name_set_of_idl typedefs
in
188 let n_consts = name_set_of_idl consts
in
189 { n_funs; n_classes; n_record_defs; n_types; n_consts }
204 let sn_funs = name_set_of_idl funs
in
205 let sn_classes = name_set_of_idl classes
in
206 let sn_record_defs = name_set_of_idl record_defs
in
207 let sn_types = name_set_of_idl typedefs
in
208 let sn_consts = name_set_of_idl consts
in
209 let s_names = { sn_funs; sn_classes; sn_record_defs; sn_types; sn_consts } in
210 { s_names; s_mode
; s_hash
}
212 let from_saved fn saved
=
213 let { s_names; s_mode
; s_hash
} = saved
in
214 let { sn_funs; sn_classes; sn_record_defs; sn_types; sn_consts } = s_names in
216 List.map
(SSet.elements
sn_funs) ~f
:(fun x
-> (File
(Fun
, fn
), x
))
219 List.map
(SSet.elements
sn_classes) ~f
:(fun x
-> (File
(Class
, fn
), x
))
222 List.map
(SSet.elements
sn_record_defs) ~f
:(fun x
->
223 (File
(RecordDef
, fn
), x
))
226 List.map
(SSet.elements
sn_types) ~f
:(fun x
-> (File
(Typedef
, fn
), x
))
229 List.map
(SSet.elements
sn_consts) ~f
:(fun x
-> (File
(Const
, fn
), x
))
242 let saved_to_names saved
=
244 n_funs = saved
.s_names.sn_funs;
245 n_classes = saved
.s_names.sn_classes;
246 n_record_defs = saved
.s_names.sn_record_defs;
247 n_types = saved
.s_names.sn_types;
248 n_consts = saved
.s_names.sn_consts;
251 let merge_names t_names1 t_names2
=
252 let { n_funs; n_classes; n_record_defs; n_types; n_consts } = t_names1
in
254 n_funs = SSet.union
n_funs t_names2
.n_funs;
255 n_classes = SSet.union
n_classes t_names2
.n_classes;
256 n_record_defs = SSet.union
n_record_defs t_names2
.n_record_defs;
257 n_types = SSet.union
n_types t_names2
.n_types;
258 n_consts = SSet.union
n_consts t_names2
.n_consts;
264 ("classes", fast
.classes);
265 ("typedefs", fast
.typedefs);
266 ("consts", fast
.consts);
268 |> List.filter ~f
:(fun (_
, l
) -> not
@@ List.is_empty l
)
269 |> List.map ~f
:(fun (kind
, l
) ->
273 (List.map l ~f
:snd
|> String.concat ~sep
:","))
274 |> String.concat ~sep
:";"
277 removed_funs
: SSet.t
;
279 removed_classes
: SSet.t
;
280 added_classes
: SSet.t
;
281 removed_types
: SSet.t
;
283 removed_consts
: SSet.t
;
284 added_consts
: SSet.t
;
289 match (f1
.hash
, f2
.hash
) with
290 | (Some h1
, Some h2
) -> Int64.equal h1 h2
296 let diff_ids ids1 ids2
=
297 let removed_ids = SSet.diff ids1 ids2
in
298 let added_ids = SSet.diff ids2 ids1
in
299 (removed_ids, added_ids)
301 let f1 = simplify f1 in
302 let f2 = simplify f2 in
303 let (removed_funs
, added_funs
) = diff_ids f1.n_funs f2.n_funs in
304 let (removed_classes
, added_classes
) = diff_ids f1.n_classes f2.n_classes in
305 let (removed_types
, added_types
) = diff_ids f1.n_types f2.n_types in
306 let (removed_consts
, added_consts
) = diff_ids f1.n_consts f2.n_consts in
309 ~f
:(fun acc s
-> (not
(SSet.is_empty s
)) || acc
)