2 * Copyright (c) 2016, Facebook, Inc.
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the "hack" directory of this source tree. An additional grant
7 * of patent rights can be found in the PATENTS file in the same directory.
15 rule_map
: Rule.t
IMap.t
;
16 rule_dependency_map
: (int list
) IMap.t
;
17 block_indentation
: int;
20 let get_rule_count t
=
21 IMap.cardinal t
.rule_map
24 (* TODO verify or log if there are unused rules *)
25 List.map
(IMap.bindings t
.rule_map
) ~f
:fst
27 let get_rule_kind t id
=
28 let r = IMap.find_unsafe id t
.rule_map
in
31 let get_char_range t
=
32 t
.chunks
|> List.fold ~init
:(max_int
,0)
33 ~f
:(fun (start_char
, end_char
) chunk
->
34 let chunk_start, chunk_end
= Chunk.get_range chunk
in
35 min start_char
chunk_start,
36 max end_char chunk_end
39 let constrain_rules t rbm rule_list
=
40 let aux rule_id
= Rule.cares_about_children
(get_rule_kind t rule_id
) in
41 let rules_that_care = List.filter rule_list ~f
:aux in
42 List.fold
rules_that_care ~init
:rbm ~f
:(fun acc k
-> IMap.add k
true acc
)
44 let get_always_rule_bindings t
=
45 let is_always_rule _k v
= v
.Rule.kind
= Rule.Always
in
46 let always_rules = IMap.filter
is_always_rule t
.rule_map
in
47 IMap.map
(fun _
-> true) always_rules
49 let get_initial_rule_bindings t
=
50 let is_always_rule _k v
= v
.Rule.kind
= Rule.Always
in
51 let always_rules = IMap.filter
is_always_rule t
.rule_map
in
52 let get_dependencies rule_id
=
53 try IMap.find_unsafe rule_id t
.rule_dependency_map
with Not_found
-> [] in
54 let constrain k _v acc
= constrain_rules t acc
(get_dependencies k
) in
55 let init_map = IMap.map
(fun _
-> true) always_rules in
56 IMap.fold
constrain always_rules init_map
58 (* When a child rule is broken on, all its parent rules must break too. *)
59 let is_dependency_satisfied parent_kind parent_val child_val
=
60 (* If the parent rule doesn't care about whether its child rules break, then
61 * the dependency doesn't matter. *)
62 if not
(Rule.cares_about_children parent_kind
) then true
64 (* Otherwise, the dependency is only unsatisfied when the parent rule is
65 * bound not to break and the child rule is bound to break. *)
66 match parent_val
, child_val
with
67 | Some
false, true -> false
70 let are_rule_bindings_valid t rbm
=
71 let valid_map = IMap.mapi
(fun rule_id v
->
72 let parent_list = try IMap.find_unsafe rule_id t
.rule_dependency_map
75 List.for_all
parent_list ~f
:(fun parent_id
->
76 let parent_rule = IMap.find_unsafe parent_id t
.rule_map
in
77 let parent_value = IMap.get parent_id rbm
in
78 is_dependency_satisfied parent_rule.Rule.kind
parent_value v
81 List.for_all ~f
:(fun x
-> x
) @@ List.map ~f
:snd
@@ IMap.bindings
valid_map
83 let dependency_map_to_string t
=
84 let get_map_values map
= List.map ~f
:snd
@@ IMap.bindings
@@ map
in
85 let str_list = get_map_values @@ IMap.mapi
(fun k v_list
->
86 let values = List.map v_list ~f
:string_of_int
in
87 string_of_int k ^
": [" ^
String.concat
", " values ^
"]"
88 ) t
.rule_dependency_map
in
89 "{" ^
String.concat
", " str_list ^
"}"