Remove enable_disk_heap setting
[hiphop-php.git] / hphp / hack / src / server / serverConfig.ml
blobce2af04bdc7d0ebef077c5447e204d3033422d8f
1 (*
2 * Copyright (c) 2015, Facebook, Inc.
3 * All rights reserved.
5 * This source code is licensed under the MIT license found in the
6 * LICENSE file in the "hack" directory of this source tree.
8 *)
10 (**
11 * Parses and gathers information from the .hhconfig in the repo.
14 open Hh_prelude
15 open Config_file.Getters
16 open Reordered_argument_collections
17 open ServerLocalConfig
19 type t = {
20 version: Config_file.version; [@printer (fun fmt _ -> fprintf fmt "version")]
21 load_script_timeout: int;
22 (* in seconds *)
23 (* Configures only the workers. Workers can have more relaxed GC configs as
24 * they are short-lived processes *)
25 gc_control: Gc.control; [@printer (fun fmt _ -> fprintf fmt "control")]
26 sharedmem_config: SharedMem.config;
27 tc_options: TypecheckerOptions.t;
28 parser_options: ParserOptions.t;
29 glean_options: GleanOptions.t;
30 symbol_write_options: SymbolWriteOptions.t;
31 formatter_override: Path.t option;
32 config_hash: string option;
33 (* A list of regexps for paths to ignore *)
34 ignored_paths: string list;
35 (* A list of extra paths to search for declarations *)
36 extra_paths: Path.t list;
37 warn_on_non_opt_build: bool;
39 [@@deriving show]
41 let filename =
42 Relative_path.from_root ~suffix:Config_file.file_path_relative_to_repo_root
44 let is_compatible c1 c2 =
45 (* This comparison can eventually be made more complex; we may not always
46 * need to restart hh_server, e.g. changing the path to the load script
47 * is immaterial*)
48 Poly.equal c1 c2
50 let make_gc_control config =
51 let { Gc.Control.minor_heap_size; space_overhead; _ } =
52 GlobalConfig.gc_control
54 let minor_heap_size =
55 int_ "gc_minor_heap_size" ~default:minor_heap_size config
57 let space_overhead =
58 int_ "gc_space_overhead" ~default:space_overhead config
60 { GlobalConfig.gc_control with Gc.Control.minor_heap_size; space_overhead }
62 let make_sharedmem_config config options local_config =
63 let { SharedMem.global_size; heap_size; shm_min_avail; _ } =
64 SharedMem.default_config
66 let shm_dirs = local_config.ServerLocalConfig.shm_dirs in
67 let global_size = int_ "sharedmem_global_size" ~default:global_size config in
68 let heap_size = int_ "sharedmem_heap_size" ~default:heap_size config in
69 let hash_table_pow = int_ "sharedmem_hash_table_pow" ~default:18 config in
70 let log_level = int_ "sharedmem_log_level" ~default:0 config in
71 let sample_rate = float_ "sharedmem_sample_rate" ~default:0.0 config in
72 let compression = int_ "sharedmem_compression" ~default:0 config in
73 let shm_dirs = string_list "sharedmem_dirs" ~default:shm_dirs config in
74 let shm_use_sharded_hashtbl =
75 bool_
76 "shm_use_sharded_hashtbl"
77 ~default:local_config.ServerLocalConfig.shm_use_sharded_hashtbl
78 config
80 let shm_cache_size =
81 int_
82 "shm_cache_size"
83 ~default:local_config.ServerLocalConfig.shm_cache_size
84 config
86 let shm_min_avail =
87 int_ "sharedmem_minimum_available" ~default:shm_min_avail config
89 let config =
91 SharedMem.global_size;
92 heap_size;
93 hash_table_pow;
94 log_level;
95 sample_rate;
96 shm_dirs;
97 shm_use_sharded_hashtbl;
98 shm_cache_size;
99 shm_min_avail;
100 compression;
103 match ServerArgs.ai_mode options with
104 | None -> config
105 | Some ai_options -> Ai_options.modify_shared_mem ai_options config
107 let config_list_regexp = Str.regexp "[, \t]+"
109 let process_experimental sl =
110 match List.map sl ~f:String.lowercase with
111 | ["false"] -> SSet.empty
112 | ["true"] -> TypecheckerOptions.experimental_all
113 | features -> List.fold_left features ~f:SSet.add ~init:SSet.empty
115 let config_experimental_tc_features config =
116 match
117 Config_file.Getters.string_opt "enable_experimental_tc_features" config
118 with
119 | None -> SSet.empty
120 | Some s ->
121 let sl = Str.split config_list_regexp s in
122 process_experimental sl
124 let process_migration_flags sl =
125 match sl with
126 | ["false"] -> SSet.empty
127 | ["true"] -> TypecheckerOptions.migration_flags_all
128 | flags ->
129 List.iter flags ~f:(fun s ->
130 if not (SSet.mem TypecheckerOptions.migration_flags_all s) then
131 failwith ("invalid migration flag: " ^ s));
132 List.fold_left flags ~f:SSet.add ~init:SSet.empty
134 let config_tc_migration_flags config =
135 Config_file.Getters.string_opt "enable_tc_migration_flags" config
136 |> Option.value_map ~f:(Str.split config_list_regexp) ~default:[]
137 |> List.map ~f:String.lowercase
138 |> process_migration_flags
140 let convert_paths str =
141 let json = Hh_json.json_of_string ~strict:true str in
142 let l = Hh_json.get_array_exn json in
143 List.filter_map
144 ~f:(fun s ->
145 match s with
146 | Hh_json.JSON_String path -> Some path
147 | _ -> None)
150 let process_ignored_paths config =
151 Config_file.Getters.string_opt "ignored_paths" config
152 |> Option.value_map ~f:convert_paths ~default:[]
154 let maybe_relative_path fn =
155 (* Note: this is not the same as calling realpath; the cwd is not
156 * necessarily the same as hh_server's root!!! *)
157 Path.make
158 begin
159 if Filename.is_relative fn then
160 Relative_path.(to_absolute (from_root ~suffix:fn))
161 else
165 let process_extra_paths config =
166 match Config_file.Getters.string_opt "extra_paths" config with
167 | Some s -> Str.split config_list_regexp s |> List.map ~f:maybe_relative_path
168 | _ -> []
170 let process_untrusted_mode config =
171 match Config_file.Getters.string_opt "untrusted_mode" config with
172 | Some s ->
173 if bool_of_string s then
174 let blacklist =
176 (* out of tree file access*)
177 "extra_paths";
178 (* potential resource abuse *)
179 "language_feature_logging";
182 let prefix_blacklist =
183 [(* potential resource abuse *) "gc_"; "sharedmem_"]
185 let invalid_keys =
186 List.filter (Config_file.keys config) ~f:(fun ck ->
187 let ck = String.lowercase ck in
188 let exact_match =
189 List.find ~f:(fun bli -> String.equal bli ck) blacklist
191 let prefix_match =
192 List.find
193 ~f:(fun blp -> String_utils.string_starts_with ck blp)
194 prefix_blacklist
196 match (exact_match, prefix_match) with
197 | (None, None) -> false
198 | _ -> true)
200 if not (List.is_empty invalid_keys) then
201 failwith
202 ("option not permitted in untrusted_mode: "
203 ^ String.concat ~sep:", " invalid_keys)
204 else
205 failwith "untrusted_mode can only be enabled, not disabled"
206 | _ -> ()
208 let extract_auto_namespace_element ns_map element =
209 match element with
210 | (source, Hh_json.JSON_String target) -> (source, target) :: ns_map
211 | _ ->
212 (* This means the JSON we received is incorrect *)
213 ns_map
215 let convert_auto_namespace_to_map map =
216 let json = Hh_json.json_of_string ~strict:true map in
217 let pairs = Hh_json.get_object_exn json in
218 (* We do a fold instead of a map to filter
219 * out the incorrect entrie as we look at each item *)
220 List.fold_left ~init:[] ~f:extract_auto_namespace_element pairs
222 let prepare_auto_namespace_map config =
223 Option.value_map
224 (Config_file.Getters.string_opt "auto_namespace_map" config)
225 ~default:[]
226 ~f:convert_auto_namespace_to_map
228 let extract_log_level = function
229 | (log_key, Hh_json.JSON_Number log_level) ->
230 begin
231 match int_of_string_opt log_level with
232 | Some log_level -> (log_key, log_level)
233 | None -> failwith "non-integer log level value"
235 | _ -> failwith "non-integer log level value"
237 let convert_log_levels_to_map map =
238 let json = Hh_json.json_of_string ~strict:true map in
239 let pairs = Hh_json.get_object_exn json in
240 List.map ~f:extract_log_level pairs |> SMap.of_list
242 let prepare_log_levels config =
243 Option.value_map
244 (Config_file.Getters.string_opt "log_levels" config)
245 ~default:SMap.empty
246 ~f:convert_log_levels_to_map
248 let prepare_iset config config_name initial_values =
249 Config_file.Getters.string_opt config_name config
250 |> Option.value_map ~f:(Str.split config_list_regexp) ~default:[]
251 |> List.map ~f:int_of_string
252 |> List.fold_right ~init:initial_values ~f:ISet.add
254 let prepare_allowed_decl_fixme_codes config =
255 prepare_iset config "allowed_decl_fixme_codes" (ISet.of_list [])
257 let load ~silent config_filename options : t * ServerLocalConfig.t =
258 let config_overrides = Config_file.of_list @@ ServerArgs.config options in
259 let (config_hash, config) =
260 Config_file.parse_hhconfig (Relative_path.to_absolute config_filename)
262 let config =
263 Config_file.apply_overrides ~from:None ~config ~overrides:config_overrides
265 process_untrusted_mode config;
266 let version =
267 Config_file.parse_version (Config_file.Getters.string_opt "version" config)
269 let local_config =
270 ServerLocalConfig.load ~silent ~current_version:version config_overrides
272 let local_config =
273 if Option.is_some (ServerArgs.ai_mode options) then
274 let open ServerLocalConfig in
276 local_config with
277 watchman =
279 local_config.watchman with
280 Watchman.enabled = false;
281 subscribe = false;
283 interrupt_on_watchman = false;
284 interrupt_on_client = false;
285 trace_parsing = false;
287 else
288 local_config
290 let ignored_paths = process_ignored_paths config in
291 let extra_paths = process_extra_paths config in
292 (* Since we use the unix alarm() for our timeouts, a timeout value of 0 means
293 * to wait indefinitely *)
294 let load_script_timeout = int_ "load_script_timeout" ~default:0 config in
295 let warn_on_non_opt_build =
296 bool_ "warn_on_non_opt_build" ~default:false config
298 let formatter_override =
299 Option.map
300 (Config_file.Getters.string_opt "formatter_override" config)
301 ~f:maybe_relative_path
303 let global_opts =
304 GlobalOptions.make
305 ?po_deregister_php_stdlib:(bool_opt "deregister_php_stdlib" config)
306 ?tco_num_local_workers:local_config.num_local_workers
307 ~tco_parallel_type_checking_threshold:
308 local_config.parallel_type_checking_threshold
309 ?tco_max_typechecker_worker_memory_mb:
310 local_config.max_typechecker_worker_memory_mb
311 ?tco_defer_class_declaration_threshold:
312 local_config.defer_class_declaration_threshold
313 ?tco_prefetch_deferred_files:(Some local_config.prefetch_deferred_files)
314 ~tco_remote_type_check_threshold:
315 ServerLocalConfig.RemoteTypeCheck.(
316 local_config.remote_type_check.remote_type_check_recheck_threshold)
317 ?tco_remote_type_check:
318 ServerLocalConfig.RemoteTypeCheck.(
319 Some local_config.remote_type_check.enabled)
320 ?tco_remote_worker_key:local_config.remote_worker_key
321 ?tco_remote_check_id:local_config.remote_check_id
322 ?tco_remote_max_batch_size:
323 ServerLocalConfig.RemoteTypeCheck.(
324 Some local_config.remote_type_check.max_batch_size)
325 ?tco_remote_min_batch_size:
326 ServerLocalConfig.RemoteTypeCheck.(
327 Some local_config.remote_type_check.min_batch_size)
328 ?tco_num_remote_workers:
329 ServerLocalConfig.RemoteTypeCheck.(
330 Some local_config.remote_type_check.num_workers)
331 ?so_remote_version_specifier:local_config.remote_version_specifier
332 ?so_remote_worker_vfs_checkout_threshold:
333 ServerLocalConfig.RemoteTypeCheck.(
334 Some local_config.remote_type_check.worker_vfs_checkout_threshold)
335 ?so_naming_sqlite_path:local_config.naming_sqlite_path
336 ?tco_language_feature_logging:(bool_opt "language_feature_logging" config)
337 ?tco_timeout:(int_opt "timeout" config)
338 ?tco_disallow_invalid_arraykey:
339 (bool_opt "disallow_invalid_arraykey" config)
340 ?tco_disallow_byref_dynamic_calls:
341 (bool_opt "disallow_byref_dynamic_calls" config)
342 ?tco_disallow_byref_calls:(bool_opt "disallow_byref_calls" config)
343 ?po_disable_lval_as_an_expression:
344 (bool_opt "disable_lval_as_an_expression" config)
345 ~allowed_fixme_codes_strict:
346 (prepare_iset config "allowed_fixme_codes_strict" ISet.empty)
347 ~po_auto_namespace_map:(prepare_auto_namespace_map config)
348 ~tco_experimental_features:(config_experimental_tc_features config)
349 ?tco_log_large_fanouts_threshold:local_config.log_large_fanouts_threshold
350 ~tco_log_inference_constraints:
351 (ServerArgs.log_inference_constraints options)
352 ~tco_migration_flags:(config_tc_migration_flags config)
353 ~tco_shallow_class_decl:local_config.ServerLocalConfig.shallow_class_decl
354 ~tco_force_shallow_decl_fanout:
355 local_config.ServerLocalConfig.force_shallow_decl_fanout
356 ~tco_remote_old_decls_no_limit:
357 local_config.ServerLocalConfig.remote_old_decls_no_limit
358 ~tco_force_load_hot_shallow_decls:
359 local_config.ServerLocalConfig.force_load_hot_shallow_decls
360 ~tco_fetch_remote_old_decls:
361 local_config.ServerLocalConfig.fetch_remote_old_decls
362 ~tco_populate_member_heaps:
363 local_config.ServerLocalConfig.populate_member_heaps
364 ~tco_skip_hierarchy_checks:
365 local_config.ServerLocalConfig.skip_hierarchy_checks
366 ~tco_skip_tast_checks:local_config.ServerLocalConfig.skip_tast_checks
367 ~po_allow_unstable_features:
368 local_config.ServerLocalConfig.allow_unstable_features
369 ?tco_like_type_hints:(bool_opt "like_type_hints" config)
370 ?tco_union_intersection_type_hints:
371 (bool_opt "union_intersection_type_hints" config)
372 ?tco_coeffects:(bool_opt "call_coeffects" config)
373 ?tco_coeffects_local:(bool_opt "local_coeffects" config)
374 ?tco_like_casts:(bool_opt "like_casts" config)
375 ?tco_simple_pessimize:(float_opt "simple_pessimize" config)
376 ?tco_check_xhp_attribute:(bool_opt "check_xhp_attribute" config)
377 ?tco_check_redundant_generics:(bool_opt "check_redundant_generics" config)
378 ?tco_disallow_unresolved_type_variables:
379 (bool_opt "disallow_unresolved_type_variables" config)
380 ?po_enable_class_level_where_clauses:
381 (bool_opt "class_level_where_clauses" config)
382 ?po_disable_legacy_soft_typehints:
383 (bool_opt "disable_legacy_soft_typehints" config)
384 ?po_disallow_toplevel_requires:
385 (bool_opt "disallow_toplevel_requires" config)
386 ~po_allowed_decl_fixme_codes:(prepare_allowed_decl_fixme_codes config)
387 ?po_allow_new_attribute_syntax:
388 (bool_opt "allow_new_attribute_syntax" config)
389 ?po_disable_legacy_attribute_syntax:
390 (bool_opt "disable_legacy_attribute_syntax" config)
391 ?tco_const_attribute:(bool_opt "const_attribute" config)
392 ?po_const_default_func_args:(bool_opt "const_default_func_args" config)
393 ?po_const_default_lambda_args:
394 (bool_opt "const_default_lambda_args" config)
395 ?po_disallow_silence:(bool_opt "disallow_silence" config)
396 ?tco_global_inference:(bool_opt "global_inference" config)
397 ?tco_gi_reinfer_types:(string_list_opt "reinfer_types" config)
398 ?tco_const_static_props:(bool_opt "const_static_props" config)
399 ?po_abstract_static_props:(bool_opt "abstract_static_props" config)
400 ~po_parser_errors_only:(Option.is_some (ServerArgs.ai_mode options))
401 ?tco_check_attribute_locations:
402 (bool_opt "check_attribute_locations" config)
403 ?glean_service:(string_opt "glean_service" config)
404 ?glean_hostname:(string_opt "glean_hostname" config)
405 ?glean_port:(int_opt "glean_port" config)
406 ?glean_reponame:(string_opt "glean_reponame" config)
407 ?symbol_write_ownership:(bool_opt "symbol_write_ownership" config)
408 ?symbol_write_root_path:(string_opt "symbol_write_root_path" config)
409 ?symbol_write_hhi_path:(string_opt "symbol_write_hhi_path" config)
410 ?symbol_write_ignore_paths:
411 (string_list_opt "symbol_write_ignore_paths" config)
412 ?symbol_write_index_paths:
413 (string_list_opt "symbol_write_index_paths" config)
414 ?symbol_write_index_paths_file:
415 (string_opt "symbol_write_index_paths_file" config)
416 ?symbol_write_index_paths_file_output:
417 (string_opt "symbol_write_index_paths_file_output" config)
418 ?symbol_write_include_hhi:(bool_opt "symbol_write_include_hhi" config)
419 ?po_disallow_func_ptrs_in_constants:
420 (bool_opt "disallow_func_ptrs_in_constants" config)
421 ?tco_error_php_lambdas:(bool_opt "error_php_lambdas" config)
422 ?tco_disallow_discarded_nullable_awaitables:
423 (bool_opt "disallow_discarded_nullable_awaitables" config)
424 ?po_disable_xhp_element_mangling:
425 (bool_opt "disable_xhp_element_mangling" config)
426 ?po_disable_xhp_children_declarations:
427 (bool_opt "disable_xhp_children_declarations" config)
428 ?po_enable_xhp_class_modifier:
429 (bool_opt "enable_xhp_class_modifier" config)
430 ?po_disable_hh_ignore_error:(int_opt "disable_hh_ignore_error" config)
431 ?tco_method_call_inference:(bool_opt "method_call_inference" config)
432 ?tco_report_pos_from_reason:(bool_opt "report_pos_from_reason" config)
433 ?tco_typecheck_sample_rate:(float_opt "typecheck_sample_rate" config)
434 ?tco_enable_sound_dynamic:(bool_opt "enable_sound_dynamic_type" config)
435 ?tco_enable_modules:(bool_opt "enable_modules" config)
436 ?po_disallow_fun_and_cls_meth_pseudo_funcs:
437 (bool_opt "disallow_fun_and_cls_meth_pseudo_funcs" config)
438 ?po_disallow_inst_meth:(bool_opt "disallow_inst_meth" config)
439 ~tco_use_direct_decl_parser:
440 local_config.ServerLocalConfig.use_direct_decl_parser
441 ~tco_ifc_enabled:(ServerArgs.enable_ifc options)
442 ~tco_global_write_check_enabled:
443 (ServerArgs.enable_global_write_check options)
444 ~tco_global_write_check_functions_enabled:
445 (ServerArgs.enable_global_write_check_functions options)
446 ?po_enable_enum_classes:(bool_opt "enable_enum_classes" config)
447 ?po_enable_enum_supertyping:(bool_opt "enable_enum_supertyping" config)
448 ?po_interpret_soft_types_as_like_types:
449 (bool_opt "interpret_soft_types_as_like_types" config)
450 ?tco_enable_strict_string_concat_interp:
451 (bool_opt "enable_strict_string_concat_interp" config)
452 ?tco_ignore_unsafe_cast:(bool_opt "ignore_unsafe_cast" config)
453 ?tco_allowed_expression_tree_visitors:
454 (Option.map
455 (string_list_opt "allowed_expression_tree_visitors" config)
456 ~f:(fun l -> List.map l ~f:Utils.add_ns))
457 ?tco_math_new_code:(bool_opt "math_new_code" config)
458 ?tco_typeconst_concrete_concrete_error:
459 (bool_opt "typeconst_concrete_concrete_error" config)
460 ?tco_enable_strict_const_semantics:
461 (let key = "enable_strict_const_semantics" in
462 match int_opt_result key config with
463 | None -> None
464 | Some (Ok i) -> Some i
465 | Some (Error _) ->
466 (* not an int *)
467 bool_opt key config |> Option.map ~f:Bool.to_int)
468 ?tco_strict_wellformedness:(int_opt "strict_wellformedness" config)
469 ?tco_meth_caller_only_public_visibility:
470 (bool_opt "meth_caller_only_public_visibility" config)
471 ?tco_require_extends_implements_ancestors:
472 (bool_opt "require_extends_implements_ancestors" config)
473 ?tco_strict_value_equality:(bool_opt "strict_value_equality" config)
474 ?tco_enforce_sealed_subclasses:
475 (bool_opt "enforce_sealed_subclasses" config)
476 ?tco_everything_sdt:(bool_opt "everything_sdt" config)
477 ?tco_pessimise_builtins:(bool_opt "pessimise_builtins" config)
478 ?tco_explicit_consistent_constructors:
479 (int_opt "explicit_consistent_constructors" config)
480 ?tco_require_types_class_consts:
481 (int_opt "require_types_tco_require_types_class_consts" config)
482 ?tco_type_printer_fuel:(int_opt "type_printer_fuel" config)
483 ?tco_is_systemlib:(bool_opt "is_systemlib" config)
484 ?tco_saved_state_manifold_api_key:
485 (Some local_config.ServerLocalConfig.saved_state_manifold_api_key)
486 ~tco_log_saved_state_age_and_distance:
487 local_config.ServerLocalConfig.log_saved_state_age_and_distance
488 ~log_levels:(prepare_log_levels config)
489 ?tco_allowed_files_for_module_declarations:
490 (string_list_opt "allowed_files_for_module_declarations" config)
491 ?tco_allow_all_files_for_module_declarations:
492 (bool_opt "allow_all_files_for_module_declarations" config)
493 ?tco_expression_tree_virtualize_functions:
494 (bool_opt "expression_tree_virtualize_functions" config)
495 ?tco_use_type_alias_heap:(bool_opt "use_type_alias_heap" config)
498 Errors.allowed_fixme_codes_strict :=
499 GlobalOptions.allowed_fixme_codes_strict global_opts;
500 Errors.report_pos_from_reason :=
501 TypecheckerOptions.report_pos_from_reason global_opts;
503 version;
504 load_script_timeout;
505 gc_control = make_gc_control config;
506 sharedmem_config = make_sharedmem_config config options local_config;
507 tc_options = global_opts;
508 parser_options = global_opts;
509 glean_options = global_opts;
510 symbol_write_options = global_opts;
511 formatter_override;
512 config_hash = Some config_hash;
513 ignored_paths;
514 extra_paths;
515 warn_on_non_opt_build;
517 local_config )
519 (* useful in testing code *)
520 let default_config =
522 version = Config_file.Opaque_version None;
523 load_script_timeout = 0;
524 gc_control = GlobalConfig.gc_control;
525 sharedmem_config = SharedMem.default_config;
526 tc_options = TypecheckerOptions.default;
527 glean_options = GleanOptions.default;
528 symbol_write_options = SymbolWriteOptions.default;
529 parser_options = ParserOptions.default;
530 formatter_override = None;
531 config_hash = None;
532 ignored_paths = [];
533 extra_paths = [];
534 warn_on_non_opt_build = false;
537 let set_parser_options config popt = { config with parser_options = popt }
539 let set_tc_options config tcopt = { config with tc_options = tcopt }
541 let set_glean_options config gleanopt = { config with glean_options = gleanopt }
543 let set_symbol_write_options config swriteopt =
544 { config with symbol_write_options = swriteopt }
546 let gc_control config = config.gc_control
548 let sharedmem_config config = config.sharedmem_config
550 let typechecker_options config = config.tc_options
552 let parser_options config = config.parser_options
554 let glean_options config = config.glean_options
556 let symbol_write_options config = config.symbol_write_options
558 let formatter_override config = config.formatter_override
560 let config_hash config = config.config_hash
562 let ignored_paths config = config.ignored_paths |> List.map ~f:Str.regexp
564 let extra_paths config = config.extra_paths
566 let version config = config.version
568 let warn_on_non_opt_build config = config.warn_on_non_opt_build