Skip to content

Commit 05cadcc

Browse files
More precise class diff in case of enum constraint changes
Summary: What the title says. So far there was no details for what changed in the enum constraints. We also export the old class kind at the top-level because it will be used for optimistic fanout algorithm. Reviewed By: bobrenjc93 Differential Revision: D37887340 fbshipit-source-id: d0ebe08e9c757a6bfe663bcae2a0f74fb09a0f7e
1 parent dd41968 commit 05cadcc

File tree

7 files changed

+186
-60
lines changed

7 files changed

+186
-60
lines changed

hphp/hack/src/decl/classDiff.ml

Lines changed: 101 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,16 @@ module ValueChange = struct
257257
| Modified of 'change
258258
[@@deriving eq, show { with_path = false }]
259259

260-
let to_json x = Hh_json.string_ @@ show (fun _ _ -> ()) x
260+
let to_json change_to_json = function
261+
| Added -> Hh_json.string_ "Added"
262+
| Removed -> Hh_json.string_ "Removed"
263+
| Modified change ->
264+
Hh_json.JSON_Object [("Modified", change_to_json change)]
265+
266+
let map ~f = function
267+
| Added -> Added
268+
| Removed -> Removed
269+
| Modified x -> Modified (f x)
261270
end
262271

263272
module NamedItemsListChange = struct
@@ -281,22 +290,15 @@ type parent_changes = {
281290
}
282291
[@@deriving eq, show { with_path = false }]
283292

293+
let classish_kind_to_json kind =
294+
Hh_json.string_ @@ Ast_defs.show_classish_kind kind
295+
284296
module KindChange = struct
285-
type t = {
286-
old_kind: Ast_defs.classish_kind;
287-
new_kind: Ast_defs.classish_kind;
288-
}
297+
type t = { new_kind: Ast_defs.classish_kind }
289298
[@@deriving eq, show { with_path = false }]
290299

291-
let classish_kind_to_json kind =
292-
Hh_json.string_ @@ Ast_defs.show_classish_kind kind
293-
294-
let to_json { old_kind; new_kind } =
295-
Hh_json.JSON_Object
296-
[
297-
("old_kind", classish_kind_to_json old_kind);
298-
("new_kind", classish_kind_to_json new_kind);
299-
]
300+
let to_json { new_kind } =
301+
Hh_json.JSON_Object [("new_kind", classish_kind_to_json new_kind)]
300302
end
301303

302304
module BoolChange = struct
@@ -308,7 +310,23 @@ module BoolChange = struct
308310
let to_json x = Hh_json.string_ @@ show x
309311
end
310312

313+
module ValueDiff = struct
314+
type 'value t = {
315+
old_value: 'value;
316+
new_value: 'value;
317+
}
318+
[@@deriving eq, show { with_path = false }]
319+
end
320+
321+
type enum_type_change = {
322+
base_change: Typing_defs.decl_ty ValueDiff.t option;
323+
constraint_change: Typing_defs.decl_ty ValueDiff.t ValueChange.t option;
324+
includes_change: unit NamedItemsListChange.t NamedItemsListChange.t option;
325+
}
326+
[@@deriving eq, show { with_path = false }]
327+
311328
type class_shell_change = {
329+
classish_kind: Ast_defs.classish_kind;
312330
parent_changes: parent_changes option;
313331
type_parameters_change: unit NamedItemsListChange.t option;
314332
kind_change: KindChange.t option;
@@ -321,7 +339,7 @@ type class_shell_change = {
321339
module_change: unit ValueChange.t option;
322340
xhp_enum_values_change: bool;
323341
user_attributes_changes: unit NamedItemsListChange.t option;
324-
enum_type_change: unit ValueChange.t option;
342+
enum_type_change: enum_type_change ValueChange.t option;
325343
}
326344
[@@deriving eq, show { with_path = false }]
327345

@@ -450,7 +468,45 @@ module ClassShellChangeCategory = struct
450468
]
451469
end
452470

471+
let unit_to_json () = Hh_json.JSON_Null
472+
473+
module EnumTypeChangeCategory = struct
474+
type t = {
475+
has_base_change: bool;
476+
constraint_change_category: unit ValueChange.t option;
477+
includes_change_category: ListChange.t option;
478+
}
479+
480+
let of_enum_type_change (change : enum_type_change) : t =
481+
let { base_change; constraint_change; includes_change } = change in
482+
{
483+
has_base_change = Option.is_some base_change;
484+
constraint_change_category =
485+
Option.map (ValueChange.map ~f:(fun _ -> ())) constraint_change;
486+
includes_change_category =
487+
Option.map ListChange.of_list_change_map includes_change;
488+
}
489+
490+
let to_json
491+
{
492+
has_base_change;
493+
constraint_change_category;
494+
includes_change_category;
495+
} =
496+
Hh_json.JSON_Object
497+
[
498+
("has_base_change", Hh_json.bool_ has_base_change);
499+
( "constraint_change_category",
500+
Hh_json.opt_
501+
(ValueChange.to_json unit_to_json)
502+
constraint_change_category );
503+
( "includes_change_category",
504+
Hh_json.opt_ ListChange.to_json includes_change_category );
505+
]
506+
end
507+
453508
type t = {
509+
classish_kind: Ast_defs.classish_kind;
454510
parent_changes_category: ParentsChangeCategory.t option;
455511
type_parameters_change_category: ListChange.t option;
456512
kind_change_category: KindChange.t option;
@@ -463,26 +519,29 @@ module ClassShellChangeCategory = struct
463519
module_change_category: unit ValueChange.t option;
464520
xhp_enum_values_change_category: bool;
465521
user_attributes_changes_category: ListChange.t option;
466-
enum_type_change_category: unit ValueChange.t option;
522+
enum_type_change_category: EnumTypeChangeCategory.t ValueChange.t option;
467523
}
468524

469525
let of_class_shell_change
470-
{
471-
parent_changes;
472-
type_parameters_change;
473-
kind_change;
474-
final_change;
475-
abstract_change;
476-
is_xhp_change;
477-
internal_change;
478-
has_xhp_keyword_change;
479-
support_dynamic_type_change;
480-
module_change;
481-
xhp_enum_values_change;
482-
user_attributes_changes;
483-
enum_type_change;
484-
} =
526+
({
527+
classish_kind;
528+
parent_changes;
529+
type_parameters_change;
530+
kind_change;
531+
final_change;
532+
abstract_change;
533+
is_xhp_change;
534+
internal_change;
535+
has_xhp_keyword_change;
536+
support_dynamic_type_change;
537+
module_change;
538+
xhp_enum_values_change;
539+
user_attributes_changes;
540+
enum_type_change;
541+
} :
542+
class_shell_change) =
485543
{
544+
classish_kind;
486545
parent_changes_category =
487546
Option.map ParentsChangeCategory.of_parents_change parent_changes;
488547
type_parameters_change_category =
@@ -498,11 +557,15 @@ module ClassShellChangeCategory = struct
498557
xhp_enum_values_change_category = xhp_enum_values_change;
499558
user_attributes_changes_category =
500559
Option.map ListChange.of_list_change_map user_attributes_changes;
501-
enum_type_change_category = enum_type_change;
560+
enum_type_change_category =
561+
Option.map
562+
(ValueChange.map ~f:EnumTypeChangeCategory.of_enum_type_change)
563+
enum_type_change;
502564
}
503565

504566
let to_json
505567
{
568+
classish_kind;
506569
parent_changes_category;
507570
type_parameters_change_category;
508571
kind_change_category;
@@ -520,6 +583,7 @@ module ClassShellChangeCategory = struct
520583
let open Hh_json in
521584
JSON_Object
522585
[
586+
("classish_kind", classish_kind_to_json classish_kind);
523587
( "parent_changes",
524588
Hh_json.opt_ ParentsChangeCategory.to_json parent_changes_category );
525589
( "type_parameters_change",
@@ -537,12 +601,15 @@ module ClassShellChangeCategory = struct
537601
Hh_json.opt_ BoolChange.to_json support_dynamic_type_change_category
538602
);
539603
( "module_change",
540-
Hh_json.opt_ ValueChange.to_json module_change_category );
604+
Hh_json.opt_ (ValueChange.to_json unit_to_json) module_change_category
605+
);
541606
("xhp_enum_values_change", Hh_json.bool_ xhp_enum_values_change_category);
542607
( "user_attributes_changes",
543608
Hh_json.opt_ ListChange.to_json user_attributes_changes_category );
544609
( "enum_type_change",
545-
Hh_json.opt_ ValueChange.to_json enum_type_change_category );
610+
Hh_json.opt_
611+
(ValueChange.to_json EnumTypeChangeCategory.to_json)
612+
enum_type_change_category );
546613
]
547614
end
548615

hphp/hack/src/decl/classDiff.mli

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,7 @@ type parent_changes = {
5757
}
5858

5959
module KindChange : sig
60-
type t = {
61-
old_kind: Ast_defs.classish_kind;
62-
new_kind: Ast_defs.classish_kind;
63-
}
64-
[@@deriving eq, show]
60+
type t = { new_kind: Ast_defs.classish_kind } [@@deriving eq, show]
6561
end
6662

6763
module BoolChange : sig
@@ -71,7 +67,23 @@ module BoolChange : sig
7167
[@@deriving eq, show]
7268
end
7369

70+
module ValueDiff : sig
71+
type 'value t = {
72+
old_value: 'value;
73+
new_value: 'value;
74+
}
75+
[@@deriving eq, show]
76+
end
77+
78+
type enum_type_change = {
79+
base_change: Typing_defs.decl_ty ValueDiff.t option;
80+
constraint_change: Typing_defs.decl_ty ValueDiff.t ValueChange.t option;
81+
includes_change: unit NamedItemsListChange.t NamedItemsListChange.t option;
82+
}
83+
[@@deriving eq, show]
84+
7485
type class_shell_change = {
86+
classish_kind: Ast_defs.classish_kind;
7587
parent_changes: parent_changes option;
7688
type_parameters_change: unit NamedItemsListChange.t option;
7789
kind_change: KindChange.t option;
@@ -84,7 +96,7 @@ type class_shell_change = {
8496
module_change: unit ValueChange.t option;
8597
xhp_enum_values_change: bool;
8698
user_attributes_changes: unit NamedItemsListChange.t option;
87-
enum_type_change: unit ValueChange.t option;
99+
enum_type_change: enum_type_change ValueChange.t option;
88100
}
89101
[@@deriving eq, show]
90102

hphp/hack/src/decl/shallow_class_diff.ml

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ let diff_of_equal equal x y =
487487
else
488488
Some ()
489489

490-
let diff_parent_lists =
490+
let diff_type_lists =
491491
diff_value_lists
492492
~equal:Typing_defs.ty_equal
493493
~get_name_value:type_name
@@ -503,26 +503,25 @@ let diff_parents (c1 : Parents.t) (c2 : Parents.t) : parent_changes option =
503503
else
504504
Some
505505
{
506-
extends_changes =
507-
diff_parent_lists c1.Parents.extends c2.Parents.extends;
506+
extends_changes = diff_type_lists c1.Parents.extends c2.Parents.extends;
508507
implements_changes =
509-
diff_parent_lists c1.Parents.implements c2.Parents.implements;
508+
diff_type_lists c1.Parents.implements c2.Parents.implements;
510509
req_extends_changes =
511-
diff_parent_lists c1.Parents.req_extends c2.Parents.req_extends;
510+
diff_type_lists c1.Parents.req_extends c2.Parents.req_extends;
512511
req_implements_changes =
513-
diff_parent_lists c1.Parents.req_implements c2.Parents.req_implements;
512+
diff_type_lists c1.Parents.req_implements c2.Parents.req_implements;
514513
req_class_changes =
515-
diff_parent_lists c1.Parents.req_class c2.Parents.req_class;
516-
uses_changes = diff_parent_lists c1.Parents.uses c2.Parents.uses;
514+
diff_type_lists c1.Parents.req_class c2.Parents.req_class;
515+
uses_changes = diff_type_lists c1.Parents.uses c2.Parents.uses;
517516
xhp_attr_changes =
518-
diff_parent_lists c1.Parents.xhp_attr_uses c2.Parents.xhp_attr_uses;
517+
diff_type_lists c1.Parents.xhp_attr_uses c2.Parents.xhp_attr_uses;
519518
}
520519

521520
let diff_kinds kind1 kind2 =
522521
if Ast_defs.equal_classish_kind kind1 kind2 then
523522
None
524523
else
525-
Some { KindChange.old_kind = kind1; new_kind = kind2 }
524+
Some { KindChange.new_kind = kind2 }
526525

527526
let diff_bools b1 b2 =
528527
match (b1, b2) with
@@ -532,20 +531,60 @@ let diff_bools b1 b2 =
532531
| (false, true) -> Some BoolChange.Became
533532
| (true, false) -> Some BoolChange.No_more
534533

535-
let diff_options option1 option2 ~equal =
534+
let diff_options option1 option2 ~diff =
536535
match (option1, option2) with
537536
| (None, None) -> None
538537
| (None, Some _) -> Some ValueChange.Added
539538
| (Some _, None) -> Some ValueChange.Removed
540539
| (Some value1, Some value2) ->
541-
if equal value1 value2 then
542-
None
543-
else
544-
Some (ValueChange.Modified ())
540+
(match diff value1 value2 with
541+
| None -> None
542+
| Some diff -> Some (ValueChange.Modified diff))
543+
544+
let diff_modules = diff_options ~diff:(diff_of_equal Ast_defs.equal_id)
545+
546+
let diff
547+
(type value)
548+
~(equal : value -> value -> bool)
549+
(old_value : value)
550+
(new_value : value) : value ValueDiff.t option =
551+
if equal old_value new_value then
552+
None
553+
else
554+
Some { ValueDiff.old_value; new_value }
555+
556+
let diff_types = diff ~equal:Typing_defs.ty_equal
557+
558+
let diff_enum_types
559+
(enum_type1 : Typing_defs.enum_type) (enum_type2 : Typing_defs.enum_type) :
560+
enum_type_change option =
561+
if Typing_defs.equal_enum_type enum_type1 enum_type2 then
562+
None
563+
else
564+
Option.some
565+
@@
566+
let {
567+
Typing_defs.te_base = base1;
568+
te_constraint = constraint1;
569+
te_includes = includes1;
570+
} =
571+
enum_type1
572+
in
573+
let {
574+
Typing_defs.te_base = base2;
575+
te_constraint = constraint2;
576+
te_includes = includes2;
577+
} =
578+
enum_type2
579+
in
545580

546-
let diff_modules = diff_options ~equal:Ast_defs.equal_id
581+
{
582+
base_change = diff_types base1 base2;
583+
constraint_change = diff_options ~diff:diff_types constraint1 constraint2;
584+
includes_change = diff_type_lists includes1 includes2;
585+
}
547586

548-
let diff_enum_types = diff_options ~equal:Typing_defs.equal_enum_type
587+
let diff_enum_type_options = diff_options ~diff:diff_enum_types
549588

550589
let user_attribute_name_value
551590
{ Typing_defs.ua_name = (_, name); ua_classname_params } =
@@ -556,6 +595,7 @@ type string_list = string list [@@deriving eq]
556595
let diff_class_shells (c1 : shallow_class) (c2 : shallow_class) :
557596
class_shell_change =
558597
{
598+
classish_kind = c1.sc_kind;
559599
parent_changes =
560600
diff_parents (Parents.of_shallow_class c1) (Parents.of_shallow_class c2);
561601
type_parameters_change =
@@ -584,7 +624,7 @@ let diff_class_shells (c1 : shallow_class) (c2 : shallow_class) :
584624
~equal:Typing_defs.equal_user_attribute
585625
~get_name_value:user_attribute_name_value
586626
~diff:(diff_of_equal equal_string_list);
587-
enum_type_change = diff_enum_types c1.sc_enum_type c2.sc_enum_type;
627+
enum_type_change = diff_enum_type_options c1.sc_enum_type c2.sc_enum_type;
588628
}
589629

590630
let diff_class (c1 : shallow_class) (c2 : shallow_class) : ClassDiff.t =

hphp/hack/src/utils/hh_json/hh_json.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,9 @@ let opt_ (to_json : 'a -> json) (x : 'a option) : json =
592592

593593
let array_ (f : 'a -> json) (xs : 'a list) : json = JSON_Array (List.map ~f xs)
594594

595+
let string_map (to_json : 'a -> json) (map : 'a SMap.t) : json =
596+
JSON_Object (SMap.bindings map |> List.map ~f:(fun (k, v) -> (k, to_json v)))
597+
595598
let get_object_exn = function
596599
| JSON_Object o -> o
597600
| _ -> assert false

0 commit comments

Comments
 (0)