Unified symbol-to-docblock server command
[hiphop-php.git] / hphp / hack / src / server / serverPrecheckedFiles.ml
blobe01a73c8a5c53e0e224741429edc3949b1fdd54c
1 (**
2 * Copyright (c) 2018, Facebook, Inc.
3 * All rights reserved.
5 * This source code is licensed under the MIT license found in the
6 * LICENSE fn in the "hack" directory of this source tree.
8 *)
10 open Core_kernel
11 open ServerEnv
13 let should_use options local_config =
14 Option.value (ServerArgs.prechecked options)
15 ~default:local_config.ServerLocalConfig.prechecked_files
17 let set env prechecked_files = { env with prechecked_files }
19 let intersect_with_master_deps ~deps ~dirty_master_deps ~rechecked_files genv env =
20 (* Compute maximum fan-out of input dep set *)
21 let deps = Typing_deps.add_all_deps deps in
22 (* See if it intersects in any way with dirty_master_deps *)
23 let common_deps = Typing_deps.DepSet.inter deps dirty_master_deps in
24 (* Expand the common part *)
25 let more_deps = Typing_deps.add_all_deps common_deps in
26 (* Remove the common part from dirty_master_deps (because after expanding it's
27 * no longer dirty. *)
28 let dirty_master_deps = Typing_deps.DepSet.diff dirty_master_deps common_deps in
30 (* Translate the dependencies to files that need to be rechecked. *)
31 let needs_recheck = Typing_deps.get_files more_deps in
32 let needs_recheck = Relative_path.Set.diff needs_recheck rechecked_files in
34 let size = Relative_path.Set.cardinal needs_recheck in
35 let env = if size = 0 then env else begin
36 ServerRevisionTracker.typing_changed genv.local_config size;
37 Hh_logger.log "Adding %d files to recheck" size;
38 let needs_recheck =
39 Relative_path.Set.union env.needs_recheck needs_recheck in
40 { env with needs_recheck }
41 end in
42 env, dirty_master_deps, size
44 let update_rechecked_files env rechecked =
45 let t = Unix.gettimeofday () in
46 let add_rechecked dirty_deps =
47 let rechecked_files = Relative_path.Map.fold rechecked
48 ~init:dirty_deps.rechecked_files
49 ~f:begin fun path _ acc ->
50 Relative_path.Set.add acc path
51 end
53 { dirty_deps with rechecked_files }
55 let env = set env @@ match env.prechecked_files with
56 | Prechecked_files_disabled -> Prechecked_files_disabled
57 | Initial_typechecking dirty_deps ->
58 Initial_typechecking (add_rechecked dirty_deps)
59 | Prechecked_files_ready dirty_deps ->
60 Prechecked_files_ready (add_rechecked dirty_deps)
62 HackEventLogger.prechecked_update_rechecked t;
63 env
65 let update_after_recheck genv env rechecked =
66 let env = update_rechecked_files env rechecked in
67 match env.full_check, env.prechecked_files with
68 | Full_check_done, Initial_typechecking {
69 dirty_local_deps;
70 dirty_master_deps;
71 rechecked_files;
72 clean_local_deps;
73 } ->
74 let t = Unix.gettimeofday () in
75 assert (Typing_deps.DepSet.is_empty clean_local_deps);
76 Hh_logger.log "Finished rechecking dirty files, evaluating their fanout";
77 (* Take any prechecked files that could have been affected by local changes
78 * and expand them too *)
79 let env, dirty_master_deps, size = intersect_with_master_deps
80 ~deps:dirty_local_deps
81 ~dirty_master_deps
82 ~rechecked_files
83 genv env
85 let env = if (size = 0) then env else begin
86 let full_check = Full_check_started in
87 let init_env = { env.init_env with needs_full_init = true } in
88 { env with init_env; full_check; }
89 end in
90 let clean_local_deps = dirty_local_deps in
91 let dirty_local_deps = Typing_deps.DepSet.empty in
92 HackEventLogger.prechecked_evaluate_init t size;
94 set env (Prechecked_files_ready {
95 dirty_local_deps;
96 dirty_master_deps;
97 rechecked_files;
98 clean_local_deps;
100 | _ -> env
102 let update_after_local_changes genv env changes =
103 match env.prechecked_files with
104 | Prechecked_files_disabled -> env
105 | Initial_typechecking dirty_deps ->
106 let dirty_local_deps =
107 Typing_deps.DepSet.union changes dirty_deps.dirty_local_deps in
108 set env (Initial_typechecking { dirty_deps with dirty_local_deps })
109 | Prechecked_files_ready dirty_deps ->
110 (* This is cleared during transition from Initial_typechecking to
111 * Prechecked_files_ready and should not be populated again *)
112 assert (Typing_deps.DepSet.is_empty dirty_deps.dirty_local_deps);
113 let changes = Typing_deps.DepSet.diff changes dirty_deps.clean_local_deps in
114 if Typing_deps.DepSet.is_empty changes then env else
115 let t = Unix.gettimeofday () in
116 let clean_local_deps =
117 Typing_deps.DepSet.union dirty_deps.clean_local_deps changes in
118 let env, dirty_master_deps, size = intersect_with_master_deps
119 ~deps:changes
120 ~dirty_master_deps:dirty_deps.dirty_master_deps
121 ~rechecked_files:dirty_deps.rechecked_files
122 genv env
124 let env = if (size = 0) then env else begin
125 let full_check = match env.full_check with
126 | Full_check_done -> Full_check_needed
127 | x -> x
129 { env with full_check; }
130 end in
131 HackEventLogger.prechecked_evaluate_incremental t size;
132 set env (Prechecked_files_ready { dirty_deps with
133 dirty_master_deps;
134 clean_local_deps;
137 let expand_all env =
138 match env.prechecked_files with
139 | Prechecked_files_disabled -> env
140 | Initial_typechecking dirty_deps
141 | Prechecked_files_ready dirty_deps ->
142 let deps = Typing_deps.add_all_deps dirty_deps.dirty_master_deps in
143 let needs_recheck = Typing_deps.get_files deps in
144 let needs_recheck =
145 Relative_path.Set.diff needs_recheck dirty_deps.rechecked_files in
146 let env = if Relative_path.Set.is_empty needs_recheck then env else begin
147 Hh_logger.log "Adding %d files to recheck after expanding all master deps"
148 (Relative_path.Set.cardinal needs_recheck);
149 let needs_recheck =
150 Relative_path.Set.union env.needs_recheck needs_recheck in
151 { env with
152 needs_recheck;
153 full_check = Full_check_started;
155 end in
156 set env (Prechecked_files_ready { dirty_deps with
157 dirty_master_deps = Typing_deps.DepSet.empty;