Skip to content

Commit f3585e2

Browse files
authored
Automatic migrations (#7829)
* migrate wip * wip migrate * pipe chain example * migrations for Js_option * migrations for Js_null * rename migration template for pipe chains * migrations for Js_null_undefined * js_float migrations * Js_int migrations * format * dict migrations * migrations for Js_date * migrations for Js_re * migrations for Js_math * one more test * migrations for js_undefined * deprecate Js_OO * migrations for Js_extern * migrations for Js_global * migrations for Js_obj * make parsing of @deprecated with migration info an experimental feature * Revert "make parsing of @deprecated with migration info an experimental feature" This reverts commit 59c902c. * typed array migrations * format * support replacing types * more type replacement migrations * support @apply.transforms for applying transforms, and add migrations for Js_promise and Js_promise2 * refactor a bit and add transform for dropping unit args in apply * refactor * finish js_json migration * more migrations * remove unused Match template * more migrations * update test fixtures * update test fixtures * more fixtures * remove * more * more * migrate .resi files as well * fix resi * migrate-all command * more migrations * migrations for Exn * change migrate summary * oops, test file * proper interfaces for Js Promise modules, so they can have migrations * format * more migration fixes * more migration fix * get rid of some warning output * update artifacts list * spec * more migrations * more migrations * analysis output * remove redundant stuff in migration templates * bool migration * more migrations * fix changelog * remove changelog entry * updates after merge * message about automatic migrations * updated analysis output * tweak message * fix subcommand
1 parent 6a9ffc1 commit f3585e2

File tree

303 files changed

+12616
-1052
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

303 files changed

+12616
-1052
lines changed

analysis/src/Cmt.ml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,17 @@ let fullsFromModule ~package ~moduleName =
5151
let loadFullCmtFromPath ~path =
5252
let uri = Uri.fromPath path in
5353
fullFromUri ~uri
54+
55+
let loadCmtInfosFromPath ~path =
56+
let uri = Uri.fromPath path in
57+
match Packages.getPackage ~uri with
58+
| None -> None
59+
| Some package -> (
60+
let moduleName =
61+
BuildSystem.namespacedName package.namespace (FindFiles.getName path)
62+
in
63+
match Hashtbl.find_opt package.pathsForModule moduleName with
64+
| Some paths ->
65+
let cmt = getCmtPath ~uri paths in
66+
Shared.tryReadCmt cmt
67+
| None -> None)

compiler/bsb/bsb_package_specs.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ let supported_format (x : string) loc : Ext_module_system.t =
5050
{loc with Lexing.pos_cnum = loc.Lexing.pos_cnum + String.length x}
5151
in
5252
let loc = {Warnings.loc_start = loc; loc_end; loc_ghost = false} in
53-
Location.deprecated loc
53+
Location.deprecated ~can_be_automigrated:false loc
5454
(Printf.sprintf "Option \"%s\" is deprecated. Use \"%s\" instead." x
5555
Literals.esmodule)
5656
in

compiler/ext/ext_list.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,3 +774,7 @@ let filter lst p =
774774
| x :: l -> if p x then find (x :: accu) l ~p else find accu l ~p
775775
in
776776
find [] lst ~p
777+
778+
let is_empty = function
779+
| [] -> true
780+
| _ :: _ -> false

compiler/ext/ext_list.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,5 @@ val filter : 'a list -> ('a -> bool) -> 'a list
231231

232232
val array_list_filter_map :
233233
'a array -> 'b list -> ('a -> 'b -> 'c option) -> 'c list
234+
235+
val is_empty : 'a list -> bool

compiler/ext/warnings.ml

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ type top_level_unit_help = FunctionCall | Other
3131
type t =
3232
| Comment_start (* 1 *)
3333
| Comment_not_end (* 2 *)
34-
| Deprecated of string * loc * loc (* 3 *)
34+
| Deprecated of string * loc * loc * bool (* 3 *)
3535
| Fragile_match of string (* 4 *)
3636
| Partial_application (* 5 *)
3737
| Method_override of string list (* 7 *)
@@ -299,14 +299,22 @@ let () = reset ()
299299
let message = function
300300
| Comment_start -> "this is the start of a comment."
301301
| Comment_not_end -> "this is not the end of a comment."
302-
| Deprecated (s, _, _) ->
302+
| Deprecated (s, _, _, can_be_automigrated) ->
303303
(* Reduce \r\n to \n:
304304
- Prevents any \r characters being printed on Unix when processing
305305
Windows sources
306306
- Prevents \r\r\n being generated on Windows, which affects the
307307
testsuite
308308
*)
309309
"deprecated: " ^ Misc.normalise_eol s
310+
^
311+
if can_be_automigrated then
312+
"\n\n\
313+
\ This can be automatically migrated by the ReScript migration tool. \
314+
Run `rescript-tools migrate-all <project-root>` to run all automatic \
315+
migrations available in your project, or `rescript-tools migrate \
316+
<file>` to migrate a single file."
317+
else ""
310318
| Fragile_match "" -> "this pattern-matching is fragile."
311319
| Fragile_match s ->
312320
"this pattern-matching is fragile.\n\
@@ -533,7 +541,7 @@ let message = function
533541
you implement this before running the code."
534542

535543
let sub_locs = function
536-
| Deprecated (_, def, use) ->
544+
| Deprecated (_, def, use, _) ->
537545
[(def, "Definition"); (use, "Expected signature")]
538546
| _ -> []
539547

compiler/ext/warnings.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ type top_level_unit_help = FunctionCall | Other
2424
type t =
2525
| Comment_start (* 1 *)
2626
| Comment_not_end (* 2 *)
27-
| Deprecated of string * loc * loc (* 3 *)
27+
| Deprecated of string * loc * loc * bool (* 3 *)
2828
| Fragile_match of string (* 4 *)
2929
| Partial_application (* 5 *)
3030
| Method_override of string list (* 7 *)

compiler/ml/builtin_attributes.ml

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,64 @@ let rec deprecated_of_attrs = function
7979
Some (string_of_opt_payload p)
8080
| _ :: tl -> deprecated_of_attrs tl
8181

82-
let check_deprecated loc attrs s =
83-
match deprecated_of_attrs attrs with
82+
let rec deprecated_of_attrs_with_migrate = function
83+
| [] -> None
84+
| ( {txt = "deprecated"; _},
85+
PStr [{pstr_desc = Pstr_eval ({pexp_desc = Pexp_record (fields, _)}, _)}]
86+
)
87+
:: _ -> (
88+
let reason =
89+
fields
90+
|> List.find_map (fun field ->
91+
match field with
92+
| {
93+
lid = {txt = Lident "reason"};
94+
x = {pexp_desc = Pexp_constant (Pconst_string (reason, _))};
95+
} ->
96+
Some reason
97+
| _ -> None)
98+
in
99+
let migration_template =
100+
fields
101+
|> List.find_map (fun field ->
102+
match field with
103+
| {lid = {txt = Lident "migrate"}; x = migration_template} ->
104+
Some migration_template
105+
| _ -> None)
106+
in
107+
let migration_in_pipe_chain_template =
108+
fields
109+
|> List.find_map (fun field ->
110+
match field with
111+
| {
112+
lid = {txt = Lident "migrateInPipeChain"};
113+
x = migration_in_pipe_chain_template;
114+
} ->
115+
Some migration_in_pipe_chain_template
116+
| _ -> None)
117+
in
118+
119+
(* TODO: Validate and error if expected shape mismatches *)
120+
match reason with
121+
| Some reason ->
122+
Some (reason, migration_template, migration_in_pipe_chain_template)
123+
| None -> None)
124+
| ({txt = "ocaml.deprecated" | "deprecated"; _}, p) :: _ ->
125+
Some (string_of_opt_payload p, None, None)
126+
| _ :: tl -> deprecated_of_attrs_with_migrate tl
127+
128+
let check_deprecated ?deprecated_context loc attrs s =
129+
match deprecated_of_attrs_with_migrate attrs with
84130
| None -> ()
85-
| Some txt -> Location.deprecated loc (cat s txt)
131+
| Some (txt, migration_template, migration_in_pipe_chain_template) ->
132+
!Cmt_utils.record_deprecated_used
133+
?deprecated_context ?migration_template ?migration_in_pipe_chain_template
134+
loc txt;
135+
Location.deprecated
136+
~can_be_automigrated:
137+
(Option.is_some migration_template
138+
|| Option.is_some migration_in_pipe_chain_template)
139+
loc (cat s txt)
86140

87141
let check_deprecated_inclusion ~def ~use loc attrs1 attrs2 s =
88142
match (deprecated_of_attrs attrs1, deprecated_of_attrs attrs2) with

compiler/ml/builtin_attributes.mli

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,12 @@
2727
ocaml.boxed / ocaml.unboxed
2828
*)
2929

30-
val check_deprecated : Location.t -> Parsetree.attributes -> string -> unit
30+
val check_deprecated :
31+
?deprecated_context:Cmt_utils.deprecated_used_context ->
32+
Location.t ->
33+
Parsetree.attributes ->
34+
string ->
35+
unit
3136
val check_deprecated_inclusion :
3237
def:Location.t ->
3338
use:Location.t ->

compiler/ml/cmt_format.ml

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ type cmt_infos = {
6363
cmt_imports : (string * Digest.t option) list;
6464
cmt_interface_digest : Digest.t option;
6565
cmt_use_summaries : bool;
66+
cmt_extra_info: Cmt_utils.cmt_extra_info;
6667
}
6768

6869
type error =
@@ -154,15 +155,30 @@ let read_cmi filename =
154155

155156
let saved_types = ref []
156157
let value_deps = ref []
158+
let deprecated_used = ref []
157159

158160
let clear () =
159161
saved_types := [];
160-
value_deps := []
162+
value_deps := [];
163+
deprecated_used := []
161164

162165
let add_saved_type b = saved_types := b :: !saved_types
163166
let get_saved_types () = !saved_types
164167
let set_saved_types l = saved_types := l
165168

169+
let record_deprecated_used ?deprecated_context ?migration_template ?migration_in_pipe_chain_template source_loc deprecated_text =
170+
deprecated_used :=
171+
{
172+
Cmt_utils.source_loc;
173+
deprecated_text;
174+
migration_template;
175+
migration_in_pipe_chain_template;
176+
context = deprecated_context;
177+
}
178+
:: !deprecated_used
179+
180+
let _ = Cmt_utils.record_deprecated_used := record_deprecated_used
181+
166182
let record_value_dependency vd1 vd2 =
167183
if vd1.Types.val_loc <> vd2.Types.val_loc then
168184
value_deps := (vd1, vd2) :: !value_deps
@@ -197,8 +213,9 @@ let save_cmt filename modname binary_annots sourcefile initial_env cmi =
197213
cmt_imports = List.sort compare (Env.imports ());
198214
cmt_interface_digest = this_crc;
199215
cmt_use_summaries = need_to_clear_env;
216+
cmt_extra_info = {deprecated_used = !deprecated_used};
200217
} in
201218
output_cmt oc cmt)
202219
end;
203220
clear ()
204-
#endif
221+
#endif

compiler/ml/cmt_format.mli

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ type cmt_infos = {
6363
cmt_imports: (string * Digest.t option) list;
6464
cmt_interface_digest: Digest.t option;
6565
cmt_use_summaries: bool;
66+
cmt_extra_info: Cmt_utils.cmt_extra_info;
6667
}
6768

6869
type error = Not_a_typedtree of string
@@ -111,6 +112,14 @@ val set_saved_types : binary_part list -> unit
111112
val record_value_dependency :
112113
Types.value_description -> Types.value_description -> unit
113114

115+
val record_deprecated_used :
116+
?deprecated_context:Cmt_utils.deprecated_used_context ->
117+
?migration_template:Parsetree.expression ->
118+
?migration_in_pipe_chain_template:Parsetree.expression ->
119+
Location.t ->
120+
string ->
121+
unit
122+
114123
(*
115124
116125
val is_magic_number : string -> bool

0 commit comments

Comments
 (0)