Make hh_single_type_check --MRO output easier to read
[hiphop-php.git] / hphp / hack / src / typing / nast_check / nast_reactivity_check.ml
blob89dba4754d18ebeb8ab93564d47b7d3f5768817b
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 file in the "hack" directory of this source tree.
8 *)
10 open Hh_prelude
11 open Aast
12 open Nast_check_env
13 module SN = Naming_special_names
15 (* Helper methods *)
16 let check_conditionally_reactive_annotation_params p params ~is_method =
17 match params with
18 | [(_, Class_const (_, (_, "class")))] -> ()
19 | _ -> Errors.conditionally_reactive_annotation_invalid_arguments ~is_method p
21 let check_conditionally_reactive_annotations
22 is_reactive p method_name user_attributes =
23 let rec check l seen =
24 match l with
25 | [] -> ()
26 | { ua_name = (_, name); ua_params } :: xs
27 when String.equal name SN.UserAttributes.uaOnlyRxIfImpl ->
28 if seen then
29 Errors.multiple_conditionally_reactive_annotations p method_name
30 else if is_reactive then
31 check_conditionally_reactive_annotation_params
32 ~is_method:true
34 ua_params;
35 check xs true
36 | _ :: xs -> check xs seen
38 check user_attributes false
40 let check_maybe_rx_attributes_on_params is_reactive parent_attrs params =
41 let parent_only_rx_if_args =
42 Naming_attributes.find SN.UserAttributes.uaAtMostRxAsArgs parent_attrs
44 let check_param seen_atmost_rx_as_rxfunc p =
45 let only_rx_if_rxfunc_attr =
46 Naming_attributes.find
47 SN.UserAttributes.uaAtMostRxAsFunc
48 p.param_user_attributes
50 let only_rx_if_impl_attr =
51 Naming_attributes.find
52 SN.UserAttributes.uaOnlyRxIfImpl
53 p.param_user_attributes
55 match (only_rx_if_rxfunc_attr, only_rx_if_impl_attr) with
56 | (Some { ua_name = (p, _); _ }, _) ->
57 if Option.is_none parent_only_rx_if_args || not is_reactive then
58 Errors.atmost_rx_as_rxfunc_invalid_location p;
59 true
60 | (_, Some { ua_name = (p, _); ua_params; _ }) ->
61 if Option.is_none parent_only_rx_if_args || not is_reactive then
62 Errors.atmost_rx_as_rxfunc_invalid_location p
63 else
64 check_conditionally_reactive_annotation_params
65 ~is_method:false
67 ua_params;
68 true
69 | _ -> seen_atmost_rx_as_rxfunc
71 let has_param_with_atmost_rx_as_rxfunc =
72 List.fold_left params ~init:false ~f:check_param
74 match (parent_only_rx_if_args, has_param_with_atmost_rx_as_rxfunc) with
75 | (Some { ua_name = (p, _); _ }, false) ->
76 Errors.no_atmost_rx_as_rxfunc_for_rx_if_args p
77 | _ -> ()
79 let handler =
80 object
81 inherit Nast_visitor.handler_base
83 method! at_fun_ env f =
84 check_maybe_rx_attributes_on_params
85 env.is_reactive
86 f.f_user_attributes
87 f.f_params
89 method! at_expr env (_, e) =
90 match e with
91 | Id (pos, cn) ->
92 if String.equal SN.Rx.is_enabled cn && not env.rx_is_enabled_allowed
93 then
94 Errors.rx_is_enabled_invalid_location pos
95 | Call ((p, Id (_, cn)), _, _, _)
96 when String.equal cn SN.Rx.move && not env.rx_move_allowed ->
97 Errors.rx_move_invalid_location p
98 | _ -> ()
100 method! at_method_ _env m =
101 let ua = m.m_user_attributes in
102 let (p, name) = m.m_name in
103 let is_reactive = fun_is_reactive ua in
104 check_conditionally_reactive_annotations is_reactive p name ua;
105 check_maybe_rx_attributes_on_params is_reactive ua m.m_params