diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e6d03896f..2cdc91a896 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ #### :nail_care: Polish - Apply heuristic to suggest using JSX fragments where we guess that might be what the user wanted. https://github.com/rescript-lang/rescript/pull/7714 +- `Int.Bitwise` functions have been deprecated. https://github.com/rescript-lang/rescript/pull/7705 # 12.0.0-beta.3 @@ -27,6 +28,7 @@ - Add optional `message` argument to `Result.getOrThrow` and improve default error message. https://github.com/rescript-lang/rescript/pull/7630 - Add `RegExp.escape` binding. https://github.com/rescript-lang/rescript/pull/7695 +- Add `Array.fromString`. https://github.com/rescript-lang/rescript/pull/7693 #### :bug: Bug fix @@ -45,6 +47,7 @@ - Suggest related functions with the expected arity in errors when it makes sense. https://github.com/rescript-lang/rescript/pull/7712 - Improve error when a constructor expects an inline record. https://github.com/rescript-lang/rescript/pull/7713 - Remove `@meth` attribute. https://github.com/rescript-lang/rescript/pull/7684 + > > > > > > > 00815832f (changelog) #### :house: Internal diff --git a/analysis/src/Cmt.ml b/analysis/src/Cmt.ml index a433d12908..ac1d5ae595 100644 --- a/analysis/src/Cmt.ml +++ b/analysis/src/Cmt.ml @@ -51,3 +51,17 @@ let fullsFromModule ~package ~moduleName = let loadFullCmtFromPath ~path = let uri = Uri.fromPath path in fullFromUri ~uri + +let loadCmtInfosFromPath ~path = + let uri = Uri.fromPath path in + match Packages.getPackage ~uri with + | None -> None + | Some package -> ( + let moduleName = + BuildSystem.namespacedName package.namespace (FindFiles.getName path) + in + match Hashtbl.find_opt package.pathsForModule moduleName with + | Some paths -> + let cmt = getCmtPath ~uri paths in + Shared.tryReadCmt cmt + | None -> None) diff --git a/compiler/ext/ext_list.ml b/compiler/ext/ext_list.ml index 7066f301ba..e7681aee30 100644 --- a/compiler/ext/ext_list.ml +++ b/compiler/ext/ext_list.ml @@ -774,3 +774,7 @@ let filter lst p = | x :: l -> if p x then find (x :: accu) l ~p else find accu l ~p in find [] lst ~p + +let is_empty = function + | [] -> true + | _ :: _ -> false diff --git a/compiler/ext/ext_list.mli b/compiler/ext/ext_list.mli index 61a07c7b38..c5e65149e9 100644 --- a/compiler/ext/ext_list.mli +++ b/compiler/ext/ext_list.mli @@ -231,3 +231,5 @@ val filter : 'a list -> ('a -> bool) -> 'a list val array_list_filter_map : 'a array -> 'b list -> ('a -> 'b -> 'c option) -> 'c list + +val is_empty : 'a list -> bool diff --git a/compiler/ml/builtin_attributes.ml b/compiler/ml/builtin_attributes.ml index 5d110eda75..8dea16c662 100644 --- a/compiler/ml/builtin_attributes.ml +++ b/compiler/ml/builtin_attributes.ml @@ -79,10 +79,58 @@ let rec deprecated_of_attrs = function Some (string_of_opt_payload p) | _ :: tl -> deprecated_of_attrs tl -let check_deprecated loc attrs s = - match deprecated_of_attrs attrs with +let rec deprecated_of_attrs_with_migrate = function + | [] -> None + | ( {txt = "deprecated"; _}, + PStr [{pstr_desc = Pstr_eval ({pexp_desc = Pexp_record (fields, _)}, _)}] + ) + :: _ -> ( + let reason = + fields + |> List.find_map (fun field -> + match field with + | { + lid = {txt = Lident "reason"}; + x = {pexp_desc = Pexp_constant (Pconst_string (reason, _))}; + } -> + Some reason + | _ -> None) + in + let migration_template = + fields + |> List.find_map (fun field -> + match field with + | {lid = {txt = Lident "migrate"}; x = migration_template} -> + Some migration_template + | _ -> None) + in + let migration_piped_template = + fields + |> List.find_map (fun field -> + match field with + | { + lid = {txt = Lident "migratePiped"}; + x = migration_piped_template; + } -> + Some migration_piped_template + | _ -> None) + in + + (* TODO: Validate and error if expected shape mismatches *) + match reason with + | Some reason -> Some (reason, migration_template, migration_piped_template) + | None -> None) + | ({txt = "ocaml.deprecated" | "deprecated"; _}, p) :: _ -> + Some (string_of_opt_payload p, None, None) + | _ :: tl -> deprecated_of_attrs_with_migrate tl + +let check_deprecated ?deprecated_context loc attrs s = + match deprecated_of_attrs_with_migrate attrs with | None -> () - | Some txt -> Location.deprecated loc (cat s txt) + | Some (txt, migration_template, migration_piped_template) -> + !Cmt_utils.record_deprecated_used + ?deprecated_context ?migration_template ?migration_piped_template loc txt; + Location.deprecated loc (cat s txt) let check_deprecated_inclusion ~def ~use loc attrs1 attrs2 s = match (deprecated_of_attrs attrs1, deprecated_of_attrs attrs2) with diff --git a/compiler/ml/builtin_attributes.mli b/compiler/ml/builtin_attributes.mli index fd898388c7..63bf762331 100644 --- a/compiler/ml/builtin_attributes.mli +++ b/compiler/ml/builtin_attributes.mli @@ -27,7 +27,12 @@ ocaml.boxed / ocaml.unboxed *) -val check_deprecated : Location.t -> Parsetree.attributes -> string -> unit +val check_deprecated : + ?deprecated_context:Cmt_utils.deprecated_used_context -> + Location.t -> + Parsetree.attributes -> + string -> + unit val check_deprecated_inclusion : def:Location.t -> use:Location.t -> diff --git a/compiler/ml/cmt_format.ml b/compiler/ml/cmt_format.ml index 907f2e7122..4b9fb2b054 100644 --- a/compiler/ml/cmt_format.ml +++ b/compiler/ml/cmt_format.ml @@ -63,6 +63,7 @@ type cmt_infos = { cmt_imports : (string * Digest.t option) list; cmt_interface_digest : Digest.t option; cmt_use_summaries : bool; + cmt_extra_info: Cmt_utils.cmt_extra_info; } type error = @@ -154,15 +155,22 @@ let read_cmi filename = let saved_types = ref [] let value_deps = ref [] +let deprecated_used = ref [] let clear () = saved_types := []; - value_deps := [] + value_deps := []; + deprecated_used := [] let add_saved_type b = saved_types := b :: !saved_types let get_saved_types () = !saved_types let set_saved_types l = saved_types := l +let record_deprecated_used ?deprecated_context ?migration_template ?migration_piped_template source_loc deprecated_text = + deprecated_used := {Cmt_utils.source_loc; deprecated_text; migration_template; migration_piped_template; context = deprecated_context} :: !deprecated_used + +let _ = Cmt_utils.record_deprecated_used := record_deprecated_used + let record_value_dependency vd1 vd2 = if vd1.Types.val_loc <> vd2.Types.val_loc then value_deps := (vd1, vd2) :: !value_deps @@ -197,6 +205,7 @@ let save_cmt filename modname binary_annots sourcefile initial_env cmi = cmt_imports = List.sort compare (Env.imports ()); cmt_interface_digest = this_crc; cmt_use_summaries = need_to_clear_env; + cmt_extra_info = {deprecated_used = !deprecated_used}; } in output_cmt oc cmt) end; diff --git a/compiler/ml/cmt_format.mli b/compiler/ml/cmt_format.mli index 1a84aa68d0..620be12e50 100644 --- a/compiler/ml/cmt_format.mli +++ b/compiler/ml/cmt_format.mli @@ -63,6 +63,7 @@ type cmt_infos = { cmt_imports: (string * Digest.t option) list; cmt_interface_digest: Digest.t option; cmt_use_summaries: bool; + cmt_extra_info: Cmt_utils.cmt_extra_info; } type error = Not_a_typedtree of string @@ -111,6 +112,14 @@ val set_saved_types : binary_part list -> unit val record_value_dependency : Types.value_description -> Types.value_description -> unit +val record_deprecated_used : + ?deprecated_context:Cmt_utils.deprecated_used_context -> + ?migration_template:Parsetree.expression -> + ?migration_piped_template:Parsetree.expression -> + Location.t -> + string -> + unit + (* val is_magic_number : string -> bool diff --git a/compiler/ml/cmt_utils.ml b/compiler/ml/cmt_utils.ml new file mode 100644 index 0000000000..f06a268427 --- /dev/null +++ b/compiler/ml/cmt_utils.ml @@ -0,0 +1,26 @@ +type deprecated_used_context = FunctionCall | Reference + +type deprecated_used = { + source_loc: Location.t; + deprecated_text: string; + migration_template: Parsetree.expression option; + migration_piped_template: Parsetree.expression option; + context: deprecated_used_context option; +} + +type cmt_extra_info = {deprecated_used: deprecated_used list} + +let record_deprecated_used : + (?deprecated_context:deprecated_used_context -> + ?migration_template:Parsetree.expression -> + ?migration_piped_template:Parsetree.expression -> + Location.t -> + string -> + unit) + ref = + ref + (fun + ?deprecated_context ?migration_template ?migration_piped_template _ _ -> + ignore deprecated_context; + ignore migration_template; + ignore migration_piped_template) diff --git a/compiler/ml/typecore.ml b/compiler/ml/typecore.ml index dd2bfa7d49..bfebac842f 100644 --- a/compiler/ml/typecore.ml +++ b/compiler/ml/typecore.ml @@ -2244,9 +2244,9 @@ type lazy_args = (Asttypes.Noloc.arg_label * (unit -> Typedtree.expression) option) list type targs = (Asttypes.Noloc.arg_label * Typedtree.expression option) list -let rec type_exp ~context ?recarg env sexp = +let rec type_exp ?deprecated_context ~context ?recarg env sexp = (* We now delegate everything to type_expect *) - type_expect ~context ?recarg env sexp (newvar ()) + type_expect ?deprecated_context ~context ?recarg env sexp (newvar ()) (* Typing of an expression with an expected type. This provide better error messages, and allows controlled @@ -2254,18 +2254,20 @@ let rec type_exp ~context ?recarg env sexp = In the principal case, [type_expected'] may be at generic_level. *) -and type_expect ~context ?in_function ?recarg env sexp ty_expected = +and type_expect ?deprecated_context ~context ?in_function ?recarg env sexp + ty_expected = let previous_saved_types = Cmt_format.get_saved_types () in let exp = Builtin_attributes.warning_scope sexp.pexp_attributes (fun () -> - type_expect_ ~context ?in_function ?recarg env sexp ty_expected) + type_expect_ ?deprecated_context ~context ?in_function ?recarg env sexp + ty_expected) in Cmt_format.set_saved_types (Cmt_format.Partial_expression exp :: previous_saved_types); exp -and type_expect_ ~context ?in_function ?(recarg = Rejected) env sexp ty_expected - = +and type_expect_ ?deprecated_context ~context ?in_function ?(recarg = Rejected) + env sexp ty_expected = let loc = sexp.pexp_loc in (* Record the expression type before unifying it with the expected type *) let rue exp = @@ -2282,7 +2284,14 @@ and type_expect_ ~context ?in_function ?(recarg = Rejected) env sexp ty_expected in match sexp.pexp_desc with | Pexp_ident lid -> - let path, desc = Typetexp.find_value env lid.loc lid.txt in + let path, desc = + Typetexp.find_value + ?deprecated_context: + (match deprecated_context with + | None -> Some Reference + | v -> v) + env lid.loc lid.txt + in (if !Clflags.annotations then let dloc = desc.Types.val_loc in let annot = @@ -2420,7 +2429,9 @@ and type_expect_ ~context ?in_function ?(recarg = Rejected) env sexp ty_expected assert (sargs <> []); begin_def (); (* one more level for non-returning functions *) - let funct = type_exp ~context:None env sfunct in + let funct = + type_exp ~deprecated_context:FunctionCall ~context:None env sfunct + in let ty = instance env funct.exp_type in end_def (); wrap_trace_gadt_instances env (lower_args env []) ty; diff --git a/compiler/ml/typetexp.ml b/compiler/ml/typetexp.ml index 942d81d663..e4de1d06eb 100644 --- a/compiler/ml/typetexp.ml +++ b/compiler/ml/typetexp.ml @@ -131,12 +131,13 @@ let find_all_constructors = let find_all_labels = find_component Env.lookup_all_labels (fun lid -> Unbound_label lid) -let find_value env loc lid = +let find_value ?deprecated_context env loc lid = Env.check_value_name (Longident.last lid) loc; let ((path, decl) as r) = find_component Env.lookup_value (fun lid -> Unbound_value lid) env loc lid in - Builtin_attributes.check_deprecated loc decl.val_attributes (Path.name path); + Builtin_attributes.check_deprecated ?deprecated_context loc + decl.val_attributes (Path.name path); r let lookup_module ?(load = false) env loc lid = diff --git a/compiler/ml/typetexp.mli b/compiler/ml/typetexp.mli index f09c26c58e..f2c1e6c191 100644 --- a/compiler/ml/typetexp.mli +++ b/compiler/ml/typetexp.mli @@ -89,7 +89,11 @@ val find_all_labels : Longident.t -> (label_description * (unit -> unit)) list val find_value : - Env.t -> Location.t -> Longident.t -> Path.t * value_description + ?deprecated_context:Cmt_utils.deprecated_used_context -> + Env.t -> + Location.t -> + Longident.t -> + Path.t * value_description val find_module : Env.t -> Location.t -> Longident.t -> Path.t * module_declaration val lookup_module : ?load:bool -> Env.t -> Location.t -> Longident.t -> Path.t diff --git a/lib/es6/Stdlib_Int.js b/lib/es6/Stdlib_Int.js index 4993a6297c..fda2d75c1f 100644 --- a/lib/es6/Stdlib_Int.js +++ b/lib/es6/Stdlib_Int.js @@ -62,6 +62,14 @@ function clamp(min, max, value) { } } +function lnot(x) { + return x ^ -1; +} + +let Bitwise = { + lnot: lnot +}; + let Ref = {}; let Constants = { @@ -75,6 +83,7 @@ export { range, rangeWithOptions, clamp, + Bitwise, Ref, } /* No side effect */ diff --git a/lib/js/Stdlib_Int.js b/lib/js/Stdlib_Int.js index 5e6dbb7ced..cece54b2a0 100644 --- a/lib/js/Stdlib_Int.js +++ b/lib/js/Stdlib_Int.js @@ -62,6 +62,14 @@ function clamp(min, max, value) { } } +function lnot(x) { + return x ^ -1; +} + +let Bitwise = { + lnot: lnot +}; + let Ref = {}; let Constants = { @@ -74,5 +82,6 @@ exports.fromString = fromString; exports.range = range; exports.rangeWithOptions = rangeWithOptions; exports.clamp = clamp; +exports.Bitwise = Bitwise; exports.Ref = Ref; /* No side effect */ diff --git a/rewatch/tests/snapshots/bs-dev-dependency-used-by-non-dev-source.txt b/rewatch/tests/snapshots/bs-dev-dependency-used-by-non-dev-source.txt index 34ddd13310..d5263d3781 100644 --- a/rewatch/tests/snapshots/bs-dev-dependency-used-by-non-dev-source.txt +++ b/rewatch/tests/snapshots/bs-dev-dependency-used-by-non-dev-source.txt @@ -1,6 +1,59 @@ -Cleaned 0/16 -Parsed 2 source files -Compiled 2 modules +Cleaned 0/15 +Parsed 3 source files +Compiled 3 modules + + Warning number 3 + /packages/dep02/src/Array.res:6:16-33 + + 4 │ let at = get + 5 │ + 6 │ let includes = Js.Array2.includes + 7 │ + 8 │ let head = t => t->get(0) + + deprecated: Js.Array2.includes + Use `Array.includes` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:24:12-25 + + 22 │ let flatMap = (t, fn) => t->map(fn)->concatMany + 23 │ + 24 │ let mapi = Js.Array2.mapi + 25 │ + 26 │ let flatten = t => t->flatMap(x => x) + + deprecated: Js.Array2.mapi + Use `Array.mapWithIndex` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:32:14-29 + + 30 │ let findIndex = (t, fn) => Js.Array.findIndex(fn, t) + 31 │ + 32 │ let filter = Js.Array2.filter + 33 │ + 34 │ let reject = (t, fn) => t->filter(el => !fn(el)) + + deprecated: Js.Array2.filter + Use `Array.filter` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:48:18-35 + + 46 │ + 47 │ module String = { + 48 │ let joinWith = Js.Array2.joinWith + 49 │ let join = joinWith(_, "") + 50 │ } + + deprecated: Js.Array2.joinWith + Use `Array.joinUnsafe` instead. + + The field 'bs-dependencies' found in the package config of '@testrepo/deprecated-config' is deprecated and will be removed in a future version. Use 'dependencies' instead. diff --git a/rewatch/tests/snapshots/dependency-cycle.txt b/rewatch/tests/snapshots/dependency-cycle.txt index b0463dddf6..99e4c0e85a 100644 --- a/rewatch/tests/snapshots/dependency-cycle.txt +++ b/rewatch/tests/snapshots/dependency-cycle.txt @@ -1,6 +1,59 @@ -Cleaned 0/16 -Parsed 1 source files -Compiled 0 modules +Cleaned 0/15 +Parsed 2 source files +Compiled 1 modules + + Warning number 3 + /packages/dep02/src/Array.res:6:16-33 + + 4 │ let at = get + 5 │ + 6 │ let includes = Js.Array2.includes + 7 │ + 8 │ let head = t => t->get(0) + + deprecated: Js.Array2.includes + Use `Array.includes` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:24:12-25 + + 22 │ let flatMap = (t, fn) => t->map(fn)->concatMany + 23 │ + 24 │ let mapi = Js.Array2.mapi + 25 │ + 26 │ let flatten = t => t->flatMap(x => x) + + deprecated: Js.Array2.mapi + Use `Array.mapWithIndex` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:32:14-29 + + 30 │ let findIndex = (t, fn) => Js.Array.findIndex(fn, t) + 31 │ + 32 │ let filter = Js.Array2.filter + 33 │ + 34 │ let reject = (t, fn) => t->filter(el => !fn(el)) + + deprecated: Js.Array2.filter + Use `Array.filter` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:48:18-35 + + 46 │ + 47 │ module String = { + 48 │ let joinWith = Js.Array2.joinWith + 49 │ let join = joinWith(_, "") + 50 │ } + + deprecated: Js.Array2.joinWith + Use `Array.joinUnsafe` instead. + + The field 'bs-dependencies' found in the package config of '@testrepo/deprecated-config' is deprecated and will be removed in a future version. Use 'dependencies' instead. diff --git a/rewatch/tests/snapshots/remove-file.txt b/rewatch/tests/snapshots/remove-file.txt index a1e2468b7f..c914b524cb 100644 --- a/rewatch/tests/snapshots/remove-file.txt +++ b/rewatch/tests/snapshots/remove-file.txt @@ -1,6 +1,59 @@ -Cleaned 1/16 -Parsed 0 source files -Compiled 1 modules +Cleaned 1/15 +Parsed 1 source files +Compiled 2 modules + + Warning number 3 + /packages/dep02/src/Array.res:6:16-33 + + 4 │ let at = get + 5 │ + 6 │ let includes = Js.Array2.includes + 7 │ + 8 │ let head = t => t->get(0) + + deprecated: Js.Array2.includes + Use `Array.includes` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:24:12-25 + + 22 │ let flatMap = (t, fn) => t->map(fn)->concatMany + 23 │ + 24 │ let mapi = Js.Array2.mapi + 25 │ + 26 │ let flatten = t => t->flatMap(x => x) + + deprecated: Js.Array2.mapi + Use `Array.mapWithIndex` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:32:14-29 + + 30 │ let findIndex = (t, fn) => Js.Array.findIndex(fn, t) + 31 │ + 32 │ let filter = Js.Array2.filter + 33 │ + 34 │ let reject = (t, fn) => t->filter(el => !fn(el)) + + deprecated: Js.Array2.filter + Use `Array.filter` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:48:18-35 + + 46 │ + 47 │ module String = { + 48 │ let joinWith = Js.Array2.joinWith + 49 │ let join = joinWith(_, "") + 50 │ } + + deprecated: Js.Array2.joinWith + Use `Array.joinUnsafe` instead. + + The field 'bs-dependencies' found in the package config of '@testrepo/deprecated-config' is deprecated and will be removed in a future version. Use 'dependencies' instead. diff --git a/rewatch/tests/snapshots/rename-file-internal-dep-namespace.txt b/rewatch/tests/snapshots/rename-file-internal-dep-namespace.txt index 55eb9df4b5..52839e6eab 100644 --- a/rewatch/tests/snapshots/rename-file-internal-dep-namespace.txt +++ b/rewatch/tests/snapshots/rename-file-internal-dep-namespace.txt @@ -1,6 +1,59 @@ -Cleaned 2/16 -Parsed 2 source files -Compiled 3 modules +Cleaned 2/15 +Parsed 3 source files +Compiled 4 modules + + Warning number 3 + /packages/dep02/src/Array.res:6:16-33 + + 4 │ let at = get + 5 │ + 6 │ let includes = Js.Array2.includes + 7 │ + 8 │ let head = t => t->get(0) + + deprecated: Js.Array2.includes + Use `Array.includes` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:24:12-25 + + 22 │ let flatMap = (t, fn) => t->map(fn)->concatMany + 23 │ + 24 │ let mapi = Js.Array2.mapi + 25 │ + 26 │ let flatten = t => t->flatMap(x => x) + + deprecated: Js.Array2.mapi + Use `Array.mapWithIndex` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:32:14-29 + + 30 │ let findIndex = (t, fn) => Js.Array.findIndex(fn, t) + 31 │ + 32 │ let filter = Js.Array2.filter + 33 │ + 34 │ let reject = (t, fn) => t->filter(el => !fn(el)) + + deprecated: Js.Array2.filter + Use `Array.filter` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:48:18-35 + + 46 │ + 47 │ module String = { + 48 │ let joinWith = Js.Array2.joinWith + 49 │ let join = joinWith(_, "") + 50 │ } + + deprecated: Js.Array2.joinWith + Use `Array.joinUnsafe` instead. + + The field 'bs-dependencies' found in the package config of '@testrepo/deprecated-config' is deprecated and will be removed in a future version. Use 'dependencies' instead. diff --git a/rewatch/tests/snapshots/rename-file-internal-dep.txt b/rewatch/tests/snapshots/rename-file-internal-dep.txt index 6596297776..a2b51f1a59 100644 --- a/rewatch/tests/snapshots/rename-file-internal-dep.txt +++ b/rewatch/tests/snapshots/rename-file-internal-dep.txt @@ -1,6 +1,59 @@ -Cleaned 2/16 -Parsed 2 source files -Compiled 2 modules +Cleaned 2/15 +Parsed 3 source files +Compiled 4 modules + + Warning number 3 + /packages/dep02/src/Array.res:6:16-33 + + 4 │ let at = get + 5 │ + 6 │ let includes = Js.Array2.includes + 7 │ + 8 │ let head = t => t->get(0) + + deprecated: Js.Array2.includes + Use `Array.includes` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:24:12-25 + + 22 │ let flatMap = (t, fn) => t->map(fn)->concatMany + 23 │ + 24 │ let mapi = Js.Array2.mapi + 25 │ + 26 │ let flatten = t => t->flatMap(x => x) + + deprecated: Js.Array2.mapi + Use `Array.mapWithIndex` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:32:14-29 + + 30 │ let findIndex = (t, fn) => Js.Array.findIndex(fn, t) + 31 │ + 32 │ let filter = Js.Array2.filter + 33 │ + 34 │ let reject = (t, fn) => t->filter(el => !fn(el)) + + deprecated: Js.Array2.filter + Use `Array.filter` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:48:18-35 + + 46 │ + 47 │ module String = { + 48 │ let joinWith = Js.Array2.joinWith + 49 │ let join = joinWith(_, "") + 50 │ } + + deprecated: Js.Array2.joinWith + Use `Array.joinUnsafe` instead. + + The field 'bs-dependencies' found in the package config of '@testrepo/deprecated-config' is deprecated and will be removed in a future version. Use 'dependencies' instead. diff --git a/rewatch/tests/snapshots/rename-file-with-interface.txt b/rewatch/tests/snapshots/rename-file-with-interface.txt index 4c2522e129..6ed7e51f13 100644 --- a/rewatch/tests/snapshots/rename-file-with-interface.txt +++ b/rewatch/tests/snapshots/rename-file-with-interface.txt @@ -1,7 +1,60 @@  No implementation file found for interface file (skipping): src/ModuleWithInterface.resi -Cleaned 2/16 -Parsed 1 source files -Compiled 2 modules +Cleaned 2/15 +Parsed 2 source files +Compiled 3 modules + + Warning number 3 + /packages/dep02/src/Array.res:6:16-33 + + 4 │ let at = get + 5 │ + 6 │ let includes = Js.Array2.includes + 7 │ + 8 │ let head = t => t->get(0) + + deprecated: Js.Array2.includes + Use `Array.includes` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:24:12-25 + + 22 │ let flatMap = (t, fn) => t->map(fn)->concatMany + 23 │ + 24 │ let mapi = Js.Array2.mapi + 25 │ + 26 │ let flatten = t => t->flatMap(x => x) + + deprecated: Js.Array2.mapi + Use `Array.mapWithIndex` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:32:14-29 + + 30 │ let findIndex = (t, fn) => Js.Array.findIndex(fn, t) + 31 │ + 32 │ let filter = Js.Array2.filter + 33 │ + 34 │ let reject = (t, fn) => t->filter(el => !fn(el)) + + deprecated: Js.Array2.filter + Use `Array.filter` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:48:18-35 + + 46 │ + 47 │ module String = { + 48 │ let joinWith = Js.Array2.joinWith + 49 │ let join = joinWith(_, "") + 50 │ } + + deprecated: Js.Array2.joinWith + Use `Array.joinUnsafe` instead. + + The field 'bs-dependencies' found in the package config of '@testrepo/deprecated-config' is deprecated and will be removed in a future version. Use 'dependencies' instead. diff --git a/rewatch/tests/snapshots/rename-file.txt b/rewatch/tests/snapshots/rename-file.txt index 29c1b2b461..bc8b44cd8f 100644 --- a/rewatch/tests/snapshots/rename-file.txt +++ b/rewatch/tests/snapshots/rename-file.txt @@ -1,6 +1,59 @@ -Cleaned 1/16 -Parsed 1 source files -Compiled 1 modules +Cleaned 1/15 +Parsed 2 source files +Compiled 2 modules + + Warning number 3 + /packages/dep02/src/Array.res:6:16-33 + + 4 │ let at = get + 5 │ + 6 │ let includes = Js.Array2.includes + 7 │ + 8 │ let head = t => t->get(0) + + deprecated: Js.Array2.includes + Use `Array.includes` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:24:12-25 + + 22 │ let flatMap = (t, fn) => t->map(fn)->concatMany + 23 │ + 24 │ let mapi = Js.Array2.mapi + 25 │ + 26 │ let flatten = t => t->flatMap(x => x) + + deprecated: Js.Array2.mapi + Use `Array.mapWithIndex` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:32:14-29 + + 30 │ let findIndex = (t, fn) => Js.Array.findIndex(fn, t) + 31 │ + 32 │ let filter = Js.Array2.filter + 33 │ + 34 │ let reject = (t, fn) => t->filter(el => !fn(el)) + + deprecated: Js.Array2.filter + Use `Array.filter` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:48:18-35 + + 46 │ + 47 │ module String = { + 48 │ let joinWith = Js.Array2.joinWith + 49 │ let join = joinWith(_, "") + 50 │ } + + deprecated: Js.Array2.joinWith + Use `Array.joinUnsafe` instead. + + The field 'bs-dependencies' found in the package config of '@testrepo/deprecated-config' is deprecated and will be removed in a future version. Use 'dependencies' instead. diff --git a/rewatch/tests/snapshots/rename-interface-file.txt b/rewatch/tests/snapshots/rename-interface-file.txt index 6eabc087b8..d9edb8ca5d 100644 --- a/rewatch/tests/snapshots/rename-interface-file.txt +++ b/rewatch/tests/snapshots/rename-interface-file.txt @@ -1,8 +1,61 @@  No implementation file found for interface file (skipping): src/ModuleWithInterface2.resi -Cleaned 1/16 -Parsed 1 source files +Cleaned 1/15 +Parsed 2 source files Compiled 2 modules + Warning number 3 + /packages/dep02/src/Array.res:6:16-33 + + 4 │ let at = get + 5 │ + 6 │ let includes = Js.Array2.includes + 7 │ + 8 │ let head = t => t->get(0) + + deprecated: Js.Array2.includes + Use `Array.includes` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:24:12-25 + + 22 │ let flatMap = (t, fn) => t->map(fn)->concatMany + 23 │ + 24 │ let mapi = Js.Array2.mapi + 25 │ + 26 │ let flatten = t => t->flatMap(x => x) + + deprecated: Js.Array2.mapi + Use `Array.mapWithIndex` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:32:14-29 + + 30 │ let findIndex = (t, fn) => Js.Array.findIndex(fn, t) + 31 │ + 32 │ let filter = Js.Array2.filter + 33 │ + 34 │ let reject = (t, fn) => t->filter(el => !fn(el)) + + deprecated: Js.Array2.filter + Use `Array.filter` instead. + + + Warning number 3 + /packages/dep02/src/Array.res:48:18-35 + + 46 │ + 47 │ module String = { + 48 │ let joinWith = Js.Array2.joinWith + 49 │ let join = joinWith(_, "") + 50 │ } + + deprecated: Js.Array2.joinWith + Use `Array.joinUnsafe` instead. + + + The field 'bs-dependencies' found in the package config of '@testrepo/deprecated-config' is deprecated and will be removed in a future version. Use 'dependencies' instead. diff --git a/runtime/Js.res b/runtime/Js.res index 4bdfdf03d1..833462bac9 100644 --- a/runtime/Js.res +++ b/runtime/Js.res @@ -203,16 +203,46 @@ external undefined: undefined<'a> = "%undefined" external typeof: 'a => string = "%typeof" /** Equivalent to console.log any value. */ -@val @scope("console") +@deprecated({ + reason: "Use `Console.log` instead.", + migrate: Console.log(), +}) +@val +@scope("console") external log: 'a => unit = "log" -@val @scope("console") external log2: ('a, 'b) => unit = "log" -@val @scope("console") external log3: ('a, 'b, 'c) => unit = "log" +@deprecated({ + reason: "Use `Console.log2` instead.", + migrate: Console.log2(), +}) +@val +@scope("console") +external log2: ('a, 'b) => unit = "log" + +@deprecated({ + reason: "Use `Console.log3` instead.", + migrate: Console.log3(), +}) +@val +@scope("console") +external log3: ('a, 'b, 'c) => unit = "log" -@val @scope("console") external log4: ('a, 'b, 'c, 'd) => unit = "log" +@deprecated({ + reason: "Use `Console.log4` instead.", + migrate: Console.log4(), +}) +@val +@scope("console") +external log4: ('a, 'b, 'c, 'd) => unit = "log" /** A convenience function to console.log more than 4 arguments */ -@val @scope("console") @variadic +@deprecated({ + reason: "Use `Console.logMany` instead.", + migrate: Console.logMany(), +}) +@val +@scope("console") +@variadic external logMany: array<'a> => unit = "log" external eqNull: ('a, null<'a>) => bool = "%equal_null" diff --git a/runtime/Js_array2.res b/runtime/Js_array2.res index 78b7afdf3a..79d89a950a 100644 --- a/runtime/Js_array2.res +++ b/runtime/Js_array2.res @@ -77,6 +77,10 @@ let strArr = Js.String.castToArrayLike("abcd") Js.Array2.from(strArr) == ["a", "b", "c", "d"] ``` */ +@deprecated({ + reason: "Use `Array.fromArrayLike` instead.", + migrate: Array.fromArrayLike(), +}) @val external from: array_like<'a> => array<'a> = "Array.from" @@ -96,6 +100,10 @@ let code = s => Js.String.charCodeAt(0, s) Js.Array2.fromMap(strArr, code) == [97.0, 98.0, 99.0, 100.0] ``` */ +@deprecated({ + reason: "Use `Array.fromArrayLikeWithMap` instead.", + migrate: Array.fromArrayLikeWithMap(), +}) @val external fromMap: (array_like<'a>, 'a => 'b) => array<'b> = "Array.from" @@ -112,6 +120,10 @@ Js.Array2.isArray(list{5, 2, 3, 1, 4}) == true Js.Array2.isArray("abcd") == false ``` */ +@deprecated({ + reason: "Use `Array.isArray` instead.", + migrate: Array.isArray(), +}) @val external isArray: 'a => bool = "Array.isArray" @@ -120,6 +132,10 @@ Returns the number of elements in the array. See [`Array.length`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/length) on MDN. */ +@deprecated({ + reason: "Use `Array.length` instead.", + migrate: Array.length(), +}) @get external length: array<'a> => int = "length" @@ -140,6 +156,10 @@ Js.Array2.copyWithin(arr, ~to_=2) == [100, 101, 100, 101, 102] arr == [100, 101, 100, 101, 102] ``` */ +@deprecated({ + reason: "Use `Array.copyAllWithin` instead.", + migrate: Array.copyAllWithin(~target=%insert.labelledArgument("to_")), +}) @send external copyWithin: (t<'a>, ~to_: int) => t<'a> = "copyWithin" @@ -160,6 +180,13 @@ Js.Array2.copyWithinFrom(arr, ~from=2, ~to_=0) == [102, 103, 104, 103, 104] arr == [102, 103, 104, 103, 104] ``` */ +@deprecated({ + reason: "Use `Array.copyWithinToEnd` instead.", + migrate: Array.copyWithinToEnd( + ~target=%insert.labelledArgument("to_"), + ~start=%insert.labelledArgument("from"), + ), +}) @send external copyWithinFrom: (t<'a>, ~to_: int, ~from: int) => t<'a> = "copyWithin" @@ -180,6 +207,13 @@ Js.Array2.copyWithinFromRange(arr, ~start=2, ~end_=5, ~to_=1) == [100, 102, 103, arr == [100, 102, 103, 104, 104, 105] ``` */ +@deprecated({ + reason: "Use `Array.copyWithin` instead.", + migrate: Array.copyWithin( + ~target=%insert.labelledArgument("to_"), + ~end=%insert.labelledArgument("end_"), + ), +}) @send external copyWithinFromRange: (t<'a>, ~to_: int, ~start: int, ~end_: int) => t<'a> = "copyWithin" @@ -202,6 +236,10 @@ Js.Array2.fillInPlace(arr, 99) == [99, 99, 99, 99, 99] arr == [99, 99, 99, 99, 99] ``` */ +@deprecated({ + reason: "Use `Array.fillAll` instead.", + migrate: Array.fillAll(), +}) @send external fillInPlace: (t<'a>, 'a) => t<'a> = "fill" @@ -222,6 +260,10 @@ Js.Array2.fillFromInPlace(arr, 99, ~from=2) == [100, 101, 99, 99, 99] arr == [100, 101, 99, 99, 99] ``` */ +@deprecated({ + reason: "Use `Array.fillToEnd` instead.", + migrate: Array.fillToEnd(~start=%insert.labelledArgument("from")), +}) @send external fillFromInPlace: (t<'a>, 'a, ~from: int) => t<'a> = "fill" @@ -243,6 +285,10 @@ Js.Array2.fillRangeInPlace(arr, 99, ~start=1, ~end_=4) == [100, 99, 99, 99, 104] arr == [100, 99, 99, 99, 104] ``` */ +@deprecated({ + reason: "Use `Array.fill` instead.", + migrate: Array.fill(~end=%insert.labelledArgument("end_")), +}) @send external fillRangeInPlace: (t<'a>, 'a, ~start: int, ~end_: int) => t<'a> = "fill" @@ -266,6 +312,10 @@ let empty: array = [] Js.Array2.pop(empty) == None ``` */ +@deprecated({ + reason: "Use `Array.pop` instead.", + migrate: Array.pop(), +}) @send external pop: t<'a> => option<'a> = "pop" @@ -283,6 +333,10 @@ Js.Array2.push(arr, "dog") == 4 arr == ["ant", "bee", "cat", "dog"] ``` */ +@deprecated({ + reason: "Use `Array.push` instead. Note: `Array.push` returns `unit`, not the array length.", + migrate: Array.push(), +}) @send external push: (t<'a>, 'a) => int = "push" @@ -301,7 +355,12 @@ Js.Array2.pushMany(arr, ["dog", "elk"]) == 5 arr == ["ant", "bee", "cat", "dog", "elk"] ``` */ -@send @variadic +@deprecated({ + reason: "Use `Array.pushMany` instead. Note: `Array.pushMany` returns `unit`, not the array length.", + migrate: Array.pushMany(), +}) +@send +@variadic external pushMany: (t<'a>, array<'a>) => int = "push" /** @@ -318,6 +377,10 @@ Js.Array2.reverseInPlace(arr) == ["cat", "bee", "ant"] arr == ["cat", "bee", "ant"] ``` */ +@deprecated({ + reason: "Use `Array.reverse` instead.", + migrate: Array.reverse(), +}) @send external reverseInPlace: t<'a> => t<'a> = "reverse" @@ -339,6 +402,10 @@ let empty: array = [] Js.Array2.shift(empty) == None ``` */ +@deprecated({ + reason: "Use `Array.shift` instead.", + migrate: Array.shift(), +}) @send external shift: t<'a> => option<'a> = "shift" @@ -362,6 +429,12 @@ Js.Array2.sortInPlace(numbers) == [1, 10, 2, 20, 3, 30] numbers == [1, 10, 2, 20, 3, 30] ``` */ +@deprecated({ + reason: "Use `Array.toSorted` instead.", + migrate: Array.toSorted((a, b) => + %todo_("This needs a comparator function. Use `String.compare` for strings, etc.") + ), +}) @send external sortInPlace: t<'a> => t<'a> = "sort" @@ -395,6 +468,10 @@ let reverseNumeric = (n1, n2) => n2 - n1 Js.Array2.sortInPlaceWith(numbers, reverseNumeric) == [30, 20, 10, 3, 2, 1] ``` */ +@deprecated({ + reason: "Use `Array.sort` instead.", + migrate: Array.sort(), +}) @send external sortInPlaceWith: (t<'a>, ('a, 'a) => int) => t<'a> = "sort" @@ -421,7 +498,16 @@ Js.Array2.spliceInPlace(arr3, ~pos=9, ~remove=2, ~add=["x", "y", "z"]) == [] arr3 == ["a", "b", "c", "d", "e", "f", "x", "y", "z"] ``` */ -@send @variadic +@send +@variadic +@deprecated({ + reason: "Use `Array.splice` instead.", + migrate: Array.splice( + ~start=%insert.labelledArgument("pos"), + ~remove=%insert.labelledArgument("remove"), + ~insert=%insert.labelledArgument("add"), + ), +}) external spliceInPlace: (t<'a>, ~pos: int, ~remove: int, ~add: array<'a>) => t<'a> = "splice" /** @@ -440,6 +526,10 @@ arr == ["a", "b", "c", "d"] ``` */ @send +@deprecated({ + reason: "Use `Array.removeInPlace` instead.", + migrate: Array.removeInPlace(%insert.labelledArgument("pos")), +}) external removeFromInPlace: (t<'a>, ~pos: int) => t<'a> = "splice" /** @@ -458,6 +548,14 @@ arr == ["a", "b", "f"] ``` */ @send +@deprecated({ + reason: "Use `Array.splice` instead.", + migrate: Array.splice( + ~start=%insert.labelledArgument("pos"), + ~remove=%insert.labelledArgument("count"), + ~insert=[], + ), +}) external removeCountInPlace: (t<'a>, ~pos: int, ~count: int) => t<'a> = "splice" /** @@ -474,6 +572,10 @@ Js.Array2.unshift(arr, "a") == 4 arr == ["a", "b", "c", "d"] ``` */ +@deprecated({ + reason: "Use `Array.unshift` instead.", + migrate: Array.unshift(), +}) @send external unshift: (t<'a>, 'a) => int = "unshift" @@ -492,7 +594,12 @@ Js.Array2.unshiftMany(arr, ["a", "b", "c"]) == 5 arr == ["a", "b", "c", "d", "e"] ``` */ -@send @variadic +@deprecated({ + reason: "Use `Array.unshiftMany` instead.", + migrate: Array.unshiftMany(), +}) +@send +@variadic external unshiftMany: (t<'a>, array<'a>) => int = "unshift" /* Accessor functions @@ -512,6 +619,10 @@ on MDN. Js.Array2.concat(["a", "b"], ["c", "d", "e"]) == ["a", "b", "c", "d", "e"] ``` */ +@deprecated({ + reason: "Use `Array.concat` instead.", + migrate: Array.concat(), +}) @send external concat: (t<'a>, t<'a>) => t<'a> = "concat" @@ -536,7 +647,12 @@ Js.Array2.concatMany(["a", "b", "c"], [["d", "e"], ["f", "g", "h"]]) == [ ] ``` */ -@send @variadic +@deprecated({ + reason: "Use `Array.concatMany` instead.", + migrate: Array.concatMany(), +}) +@send +@variadic external concatMany: (t<'a>, array>) => t<'a> = "concat" /** @@ -551,6 +667,10 @@ Js.Array2.includes(["a", "b", "c"], "b") == true Js.Array2.includes(["a", "b", "c"], "x") == false ``` */ +@deprecated({ + reason: "Use `Array.includes` instead.", + migrate: Array.includes(), +}) @send external includes: (t<'a>, 'a) => bool = "includes" @@ -567,6 +687,10 @@ Js.Array2.indexOf([100, 101, 102, 103], 102) == 2 Js.Array2.indexOf([100, 101, 102, 103], 999) == -1 ``` */ +@deprecated({ + reason: "Use `Array.indexOf` instead.", + migrate: Array.indexOf(), +}) @send external indexOf: (t<'a>, 'a) => int = "indexOf" @@ -584,6 +708,10 @@ Js.Array2.indexOfFrom(["a", "b", "a", "c", "a"], "a", ~from=3) == 4 Js.Array2.indexOfFrom(["a", "b", "a", "c", "a"], "b", ~from=2) == -1 ``` */ +@deprecated({ + reason: "Use `Array.indexOfFrom` instead.", + migrate: Array.indexOfFrom(%insert.labelledArgument("from")), +}) @send external indexOfFrom: (t<'a>, 'a, ~from: int) => int = "indexOf" @@ -603,6 +731,10 @@ Js.Array2.joinWith([2020, 9, 4], "/") == "2020/9/4" Js.Array2.joinWith([2.5, 3.6, 3e-2], ";") == "2.5;3.6;0.03" ``` */ +@deprecated({ + reason: "Use `Array.joinUnsafe` instead.", + migrate: Array.joinUnsafe(), +}) @send external joinWith: (t<'a>, string) => string = "join" @@ -619,6 +751,10 @@ Js.Array2.lastIndexOf(["a", "b", "a", "c"], "a") == 2 Js.Array2.lastIndexOf(["a", "b", "a", "c"], "x") == -1 ``` */ +@deprecated({ + reason: "Use `Array.lastIndexOf` instead.", + migrate: Array.lastIndexOf(), +}) @send external lastIndexOf: (t<'a>, 'a) => int = "lastIndexOf" @@ -636,6 +772,10 @@ Js.Array2.lastIndexOfFrom(["a", "b", "a", "c", "a", "d"], "a", ~from=3) == 2 Js.Array2.lastIndexOfFrom(["a", "b", "a", "c", "a", "d"], "c", ~from=2) == -1 ``` */ +@deprecated({ + reason: "Use `Array.lastIndexOfFrom` instead.", + migrate: Array.lastIndexOfFrom(%insert.labelledArgument("from")), +}) @send external lastIndexOfFrom: (t<'a>, 'a, ~from: int) => int = "lastIndexOf" @@ -655,6 +795,10 @@ Js.Array2.slice(arr, ~start=-3, ~end_=-1) == [104, 105] Js.Array2.slice(arr, ~start=9, ~end_=10) == [] ``` */ +@deprecated({ + reason: "Use `Array.slice` instead.", + migrate: Array.slice(~end=%insert.labelledArgument("end_")), +}) @send external slice: (t<'a>, ~start: int, ~end_: int) => t<'a> = "slice" @@ -664,6 +808,10 @@ Returns a copy of the entire array. Same as `Js.Array2.Slice(arr, ~start=0, [`Array.slice`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice) on MDN. */ +@deprecated({ + reason: "Use `Array.copy` instead.", + migrate: Array.copy(), +}) @send external copy: t<'a> => t<'a> = "slice" @@ -672,6 +820,10 @@ Returns a shallow copy of the given array from the given index to the end. See [`Array.slice`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice) on MDN. */ +@deprecated({ + reason: "Use `Array.sliceToEnd` instead.", + migrate: Array.sliceToEnd(~start=%insert.unlabelledArgument(1)), +}) @send external sliceFrom: (t<'a>, int) => t<'a> = "slice" @@ -689,6 +841,10 @@ Js.Array2.toString([3.5, 4.6, 7.8]) == "3.5,4.6,7.8" Js.Array2.toString(["a", "b", "c"]) == "a,b,c" ``` */ +@deprecated({ + reason: "Use `Array.toString` instead.", + migrate: Array.toString(), +}) @send external toString: t<'a> => string = "toString" @@ -708,6 +864,10 @@ Js.Array2.toLocaleString([Js.Date.make()]) // returns "2020-3-19 10:52:11" for locale de_DE.utf8 ``` */ +@deprecated({ + reason: "Use `Array.toLocaleString` instead.", + migrate: Array.toLocaleString(), +}) @send external toLocaleString: t<'a> => string = "toLocaleString" @@ -733,6 +893,10 @@ Js.Array2.every([6, 22, 8, 4], isEven) == true Js.Array2.every([6, 22, 7, 4], isEven) == false ``` */ +@deprecated({ + reason: "Use `Array.every` instead.", + migrate: Array.every(), +}) @send external every: (t<'a>, 'a => bool) => bool = "every" @@ -755,6 +919,10 @@ Js.Array2.everyi([6, -3, 5, 8], evenIndexPositive) == true Js.Array2.everyi([6, 3, -5, 8], evenIndexPositive) == false ``` */ +@deprecated({ + reason: "Use `Array.everyWithIndex` instead.", + migrate: Array.everyWithIndex(), +}) @send external everyi: (t<'a>, ('a, int) => bool) => bool = "every" @@ -772,6 +940,10 @@ let nonEmpty = s => s != "" Js.Array2.filter(["abc", "", "", "def", "ghi"], nonEmpty) == ["abc", "def", "ghi"] ``` */ +@deprecated({ + reason: "Use `Array.filter` instead.", + migrate: Array.filter(), +}) @send external filter: (t<'a>, 'a => bool) => t<'a> = "filter" @@ -793,6 +965,10 @@ let positiveOddElement = (item, index) => mod(index, 2) == 1 && item > 0 Js.Array2.filteri([6, 3, 5, 8, 7, -4, 1], positiveOddElement) == [3, 8] ``` */ +@deprecated({ + reason: "Use `Array.filterWithIndex` instead.", + migrate: Array.filterWithIndex(), +}) @send external filteri: (t<'a>, ('a, int) => bool) => t<'a> = "filter" @@ -810,6 +986,10 @@ Js.Array2.find([33, 22, -55, 77, -44], x => x < 0) == Some(-55) Js.Array2.find([33, 22, 55, 77, 44], x => x < 0) == None ``` */ +@deprecated({ + reason: "Use `Array.find` instead.", + migrate: Array.find(), +}) @send external find: (t<'a>, 'a => bool) => option<'a> = "find" @@ -832,6 +1012,10 @@ Js.Array2.findi([66, -33, 55, 88, 22], positiveOddElement) == Some(88) Js.Array2.findi([66, -33, 55, -88, 22], positiveOddElement) == None ``` */ +@deprecated({ + reason: "Use `Array.findWithIndex` instead.", + migrate: Array.findWithIndex(), +}) @send external findi: (t<'a>, ('a, int) => bool) => option<'a> = "find" @@ -850,6 +1034,10 @@ Js.Array2.findIndex([33, 22, -55, 77, -44], x => x < 0) == 2 Js.Array2.findIndex([33, 22, 55, 77, 44], x => x < 0) == -1 ``` */ +@deprecated({ + reason: "Use `Array.findIndex` instead.", + migrate: Array.findIndex(), +}) @send external findIndex: (t<'a>, 'a => bool) => int = "findIndex" @@ -872,6 +1060,10 @@ Js.Array2.findIndexi([66, -33, 55, 88, 22], positiveOddElement) == 3 Js.Array2.findIndexi([66, -33, 55, -88, 22], positiveOddElement) == -1 ``` */ +@deprecated({ + reason: "Use `Array.findIndexWithIndex` instead.", + migrate: Array.findIndexWithIndex(), +}) @send external findIndexi: (t<'a>, ('a, int) => bool) => int = "findIndex" @@ -893,6 +1085,10 @@ on MDN. Js.Array2.forEach(["a", "b", "c"], x => Js.log(x)) == () ``` */ +@deprecated({ + reason: "Use `Array.forEach` instead.", + migrate: Array.forEach(), +}) @send external forEach: (t<'a>, 'a => unit) => unit = "forEach" @@ -913,6 +1109,10 @@ on MDN. Js.Array2.forEachi(["a", "b", "c"], (item, index) => Js.log2(index + 1, item)) == () ``` */ +@deprecated({ + reason: "Use `Array.forEachWithIndex` instead.", + migrate: Array.forEachWithIndex(), +}) @send external forEachi: (t<'a>, ('a, int) => unit) => unit = "forEach" @@ -934,6 +1134,10 @@ Js.Array2.map([12, 4, 8], x => x * x) == [144, 16, 64] Js.Array2.map(["animal", "vegetable", "mineral"], Js.String.length) == [6, 9, 7] ``` */ +@deprecated({ + reason: "Use `Array.map` instead.", + migrate: Array.map(), +}) @send external map: (t<'a>, 'a => 'b) => t<'b> = "map" @@ -953,6 +1157,10 @@ let product = (item, index) => item * index Js.Array2.mapi([10, 11, 12], product) == [0, 11, 24] ``` */ +@deprecated({ + reason: "Use `Array.mapWithIndex` instead.", + migrate: Array.mapWithIndex(), +}) @send external mapi: (t<'a>, ('a, int) => 'b) => t<'b> = "map" @@ -987,6 +1195,10 @@ Js.Array2.reduce( Js.Array2.reduce([2.0, 4.0], (acc, item) => item /. acc, 1.0) == 2.0 // 4.0 / (2.0 / 1.0) ``` */ +@deprecated({ + reason: "Use `Array.reduce` instead.", + migrate: Array.reduce(%insert.unlabelledArgument(2), %insert.unlabelledArgument(1)), +}) @send external reduce: (t<'a>, ('b, 'a) => 'b, 'b) => 'b = "reduce" @@ -1023,6 +1235,10 @@ Js.Array2.reducei([2, 5, 1, 4, 3], sumOfEvens, 0) == 6 ``` */ @send +@deprecated({ + reason: "Use `Array.reduceWithIndex` instead.", + migrate: Array.reduceWithIndex(%insert.unlabelledArgument(2), %insert.unlabelledArgument(1)), +}) external reducei: (t<'a>, ('b, 'a, int) => 'b, 'b) => 'b = "reduce" /** @@ -1055,6 +1271,10 @@ Js.Array2.reduceRight([2.0, 4.0], (acc, item) => item /. acc, 1.0) == 0.5 // 2.0 ``` */ @send +@deprecated({ + reason: "Use `Array.reduceRight` instead.", + migrate: Array.reduceRight(%insert.unlabelledArgument(2), %insert.unlabelledArgument(1)), +}) external reduceRight: (t<'a>, ('b, 'a) => 'b, 'b) => 'b = "reduceRight" /** @@ -1092,6 +1312,10 @@ Js.Array2.reduceRighti([2, 5, 1, 4, 3], sumOfEvens, 0) == 6 ``` */ @send +@deprecated({ + reason: "Use `Array.reduceRightWithIndex` instead.", + migrate: Array.reduceRightWithIndex(%insert.unlabelledArgument(2), %insert.unlabelledArgument(1)), +}) external reduceRighti: (t<'a>, ('b, 'a, int) => 'b, 'b) => 'b = "reduceRight" /** @@ -1107,6 +1331,10 @@ Js.Array2.some([3, 7, 5, 2, 9], isEven) == true Js.Array2.some([3, 7, 5, 1, 9], isEven) == false ``` */ +@deprecated({ + reason: "Use `Array.some` instead.", + migrate: Array.some(), +}) @send external some: (t<'a>, 'a => bool) => bool = "some" @@ -1130,6 +1358,10 @@ Js.Array2.somei(["ab", "cd", "ef", "gh"], sameLength) == true Js.Array2.somei(["a", "bc", "def", "gh"], sameLength) == false ``` */ +@deprecated({ + reason: "Use `Array.someWithIndex` instead.", + migrate: Array.someWithIndex(), +}) @send external somei: (t<'a>, ('a, int) => bool) => bool = "some" @@ -1149,6 +1381,10 @@ Js.Array2.unsafe_get(arr, 3) == 103 Js.Array2.unsafe_get(arr, 4) // returns undefined ``` */ +@deprecated({ + reason: "Use `Array.getUnsafe` instead.", + migrate: Array.getUnsafe(), +}) external unsafe_get: (array<'a>, int) => 'a = "%array_unsafe_get" /** @@ -1174,4 +1410,8 @@ Js.Array2.unsafe_set(arr, -1, 66) // you don't want to know. ``` */ +@deprecated({ + reason: "Use `Array.setUnsafe` instead.", + migrate: Array.setUnsafe(), +}) external unsafe_set: (array<'a>, int, 'a) => unit = "%array_unsafe_set" diff --git a/runtime/Js_bigint.res b/runtime/Js_bigint.res index e19daff867..4695f8128b 100644 --- a/runtime/Js_bigint.res +++ b/runtime/Js_bigint.res @@ -30,6 +30,10 @@ try { } ``` */ +@deprecated({ + reason: "Use `fromStringOrThrow` instead", + migrate: BigInt.fromStringOrThrow(), +}) @val external fromStringExn: string => bigint = "BigInt" @@ -44,13 +48,45 @@ external \"/": (bigint, bigint) => bigint = "%divbigint" external mod: (bigint, bigint) => bigint = "%modbigint" external \"**": (bigint, bigint) => bigint = "%powbigint" +@deprecated({ + reason: "Use `&` operator or `BigInt.bitwiseAnd` instead.", + migrate: %insert.unlabelledArgument(0) & %insert.unlabelledArgument(1), + migratePiped: BigInt.bitwiseAnd(), +}) external land: (bigint, bigint) => bigint = "%andbigint" + +@deprecated({ + reason: "Use `bitwiseOr` instead.", + migrate: BigInt.bitwiseOr(), +}) external lor: (bigint, bigint) => bigint = "%orbigint" + +@deprecated({ + reason: "Use `^` operator or `BigInt.bitwiseXor` instead.", + migrate: %insert.unlabelledArgument(0) ^ %insert.unlabelledArgument(1), + migratePiped: BigInt.bitwiseXor(), +}) external lxor: (bigint, bigint) => bigint = "%xorbigint" +@deprecated({ + reason: "Use `~` operator or `BigInt.bitwiseNot` instead.", + migrate: ~(%insert.unlabelledArgument(0)), + migratePiped: BigInt.bitwiseNot(), +}) let lnot = x => lxor(x, -1n) +@deprecated({ + reason: "Use `<<` operator or `BigInt.shiftLeft` instead.", + migrate: %insert.unlabelledArgument(0) << %insert.unlabelledArgument(1), + migratePiped: BigInt.shiftLeft(), +}) external lsl: (bigint, bigint) => bigint = "%lslbigint" + +@deprecated({ + reason: "Use `>>` operator or `BigInt.shiftRight` instead.", + migrate: %insert.unlabelledArgument(0) >> %insert.unlabelledArgument(1), + migratePiped: BigInt.shiftRight(), +}) external asr: (bigint, bigint) => bigint = "%asrbigint" /** @@ -64,6 +100,10 @@ See [`toString`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Referen Js.BigInt.toString(123n)->Js.log ``` */ +@deprecated({ + reason: "Use `BigInt.toString` instead.", + migrate: BigInt.toString(), +}) @send external toString: bigint => string = "toString" @@ -77,5 +117,9 @@ Returns a string with a language-sensitive representation of this BigInt value. Js.BigInt.toString(123n)->Js.log ``` */ +@deprecated({ + reason: "Use `BigInt.toLocaleString` instead.", + migrate: BigInt.toLocaleString(), +}) @send external toLocaleString: bigint => string = "toLocaleString" diff --git a/runtime/Js_console.res b/runtime/Js_console.res index 9e0eda90c7..594ff1bb61 100644 --- a/runtime/Js_console.res +++ b/runtime/Js_console.res @@ -1,29 +1,195 @@ -@val @scope("console") external log: 'a => unit = "log" -@val @scope("console") external log2: ('a, 'b) => unit = "log" -@val @scope("console") external log3: ('a, 'b, 'c) => unit = "log" -@val @scope("console") external log4: ('a, 'b, 'c, 'd) => unit = "log" -@val @scope("console") @variadic external logMany: array<'a> => unit = "log" - -@val @scope("console") external info: 'a => unit = "info" -@val @scope("console") external info2: ('a, 'b) => unit = "info" -@val @scope("console") external info3: ('a, 'b, 'c) => unit = "info" -@val @scope("console") external info4: ('a, 'b, 'c, 'd) => unit = "info" -@val @scope("console") @variadic external infoMany: array<'a> => unit = "info" - -@val @scope("console") external warn: 'a => unit = "warn" -@val @scope("console") external warn2: ('a, 'b) => unit = "warn" -@val @scope("console") external warn3: ('a, 'b, 'c) => unit = "warn" -@val @scope("console") external warn4: ('a, 'b, 'c, 'd) => unit = "warn" -@val @scope("console") @variadic external warnMany: array<'a> => unit = "warn" - -@val @scope("console") external error: 'a => unit = "error" -@val @scope("console") external error2: ('a, 'b) => unit = "error" -@val @scope("console") external error3: ('a, 'b, 'c) => unit = "error" -@val @scope("console") external error4: ('a, 'b, 'c, 'd) => unit = "error" -@val @scope("console") @variadic external errorMany: array<'a> => unit = "error" - -@val @scope("console") external trace: unit => unit = "trace" - -@val @scope("console") external timeStart: string => unit = "time" - -@val @scope("console") external timeEnd: string => unit = "timeEnd" +@deprecated({ + reason: "Use `Console.log` instead.", + migrate: Console.log(), +}) +@val +@scope("console") +external log: 'a => unit = "log" + +@deprecated({ + reason: "Use `Console.log2` instead.", + migrate: Console.log2(), +}) +@val +@scope("console") +external log2: ('a, 'b) => unit = "log" + +@deprecated({ + reason: "Use `Console.log3` instead.", + migrate: Console.log3(), +}) +@val +@scope("console") +external log3: ('a, 'b, 'c) => unit = "log" + +@deprecated({ + reason: "Use `Console.log4` instead.", + migrate: Console.log4(), +}) +@val +@scope("console") +external log4: ('a, 'b, 'c, 'd) => unit = "log" + +@deprecated({ + reason: "Use `Console.logMany` instead.", + migrate: Console.logMany(), +}) +@val +@scope("console") +@variadic +external logMany: array<'a> => unit = "log" + +@deprecated({ + reason: "Use `Console.info` instead.", + migrate: Console.info(), +}) +@val +@scope("console") +external info: 'a => unit = "info" + +@deprecated({ + reason: "Use `Console.info2` instead.", + migrate: Console.info2(), +}) +@val +@scope("console") +external info2: ('a, 'b) => unit = "info" + +@deprecated({ + reason: "Use `Console.info3` instead.", + migrate: Console.info3(), +}) +@val +@scope("console") +external info3: ('a, 'b, 'c) => unit = "info" + +@deprecated({ + reason: "Use `Console.info4` instead.", + migrate: Console.info4(), +}) +@val +@scope("console") +external info4: ('a, 'b, 'c, 'd) => unit = "info" + +@deprecated({ + reason: "Use `Console.infoMany` instead.", + migrate: Console.infoMany(), +}) +@val +@scope("console") +@variadic +external infoMany: array<'a> => unit = "info" + +@deprecated({ + reason: "Use `Console.warn` instead.", + migrate: Console.warn(), +}) +@val +@scope("console") +external warn: 'a => unit = "warn" + +@deprecated({ + reason: "Use `Console.warn2` instead.", + migrate: Console.warn2(), +}) +@val +@scope("console") +external warn2: ('a, 'b) => unit = "warn" + +@deprecated({ + reason: "Use `Console.warn3` instead.", + migrate: Console.warn3(), +}) +@val +@scope("console") +external warn3: ('a, 'b, 'c) => unit = "warn" + +@deprecated({ + reason: "Use `Console.warn4` instead.", + migrate: Console.warn4(), +}) +@val +@scope("console") +external warn4: ('a, 'b, 'c, 'd) => unit = "warn" + +@deprecated({ + reason: "Use `Console.warnMany` instead.", + migrate: Console.warnMany(), +}) +@val +@scope("console") +@variadic +external warnMany: array<'a> => unit = "warn" + +@deprecated({ + reason: "Use `Console.error` instead.", + migrate: Console.error(), +}) +@val +@scope("console") +external error: 'a => unit = "error" + +@deprecated({ + reason: "Use `Console.error2` instead.", + migrate: Console.error2(), +}) +@val +@scope("console") +external error2: ('a, 'b) => unit = "error" + +@deprecated({ + reason: "Use `Console.error3` instead.", + migrate: Console.error3(), +}) +@val +@scope("console") +external error3: ('a, 'b, 'c) => unit = "error" + +@deprecated({ + reason: "Use `Console.error4` instead.", + migrate: Console.error4(), +}) +@val +@scope("console") +external error4: ('a, 'b, 'c, 'd) => unit = "error" + +@deprecated({ + reason: "Use `Console.errorMany` instead.", + migrate: Console.errorMany(), +}) +@val +@scope("console") +@variadic +external errorMany: array<'a> => unit = "error" + +@deprecated({ + reason: "Use `Console.trace` instead.", + migrate: Console.trace(), +}) +@val +@scope("console") +external trace: unit => unit = "trace" + +@deprecated({ + reason: "Use `Console.time` instead.", + migrate: Console.time(), +}) +@val +@scope("console") +external timeStart: string => unit = "time" + +@deprecated({ + reason: "Use `Console.timeEnd` instead.", + migrate: Console.timeEnd(), +}) +@val +@scope("console") +external timeEnd: string => unit = "timeEnd" + +@deprecated({ + reason: "Use `Console.table` instead.", + migrate: Console.table(), +}) +@val +@scope("console") +external table: 'a => unit = "table" diff --git a/runtime/Js_json.resi b/runtime/Js_json.resi index 4dce84f7ea..7e18bf6828 100644 --- a/runtime/Js_json.resi +++ b/runtime/Js_json.resi @@ -73,6 +73,13 @@ let test: ('a, Kind.t<'b>) => bool /** `decodeString(json)` returns `Some(s)` if `json` is a `string`, `None` otherwise. */ +@deprecated({ + reason: "Use pattern matching instead.", + migrate: switch %insert.unlabelledArgument(0) { + | JSON.String(str) => Some(str) + | _ => None + }, +}) let decodeString: t => option /** diff --git a/runtime/Js_string2.res b/runtime/Js_string2.res index 700b54a0c4..34257c5a3b 100644 --- a/runtime/Js_string2.res +++ b/runtime/Js_string2.res @@ -36,6 +36,10 @@ Js.String2.make(3.5) == "3.5" Js.String2.make([1, 2, 3]) == "1,2,3" ``` */ +@deprecated({ + reason: "Use `String.make` instead", + migrate: String.make(), +}) @val external make: 'a => t = "String" @@ -57,6 +61,10 @@ Js.String2.fromCharCode(0xd55c) == `한` Js.String2.fromCharCode(-64568) == `ψ` ``` */ +@deprecated({ + reason: "Use `String.fromCharCode` instead", + migrate: String.fromCharCode(), +}) @val external fromCharCode: int => t = "String.fromCharCode" @@ -67,7 +75,12 @@ corresponding to the given numbers, using the same rules as `fromCharCode`. See [`String.fromCharCode`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCharCode) on MDN. */ -@val @variadic +@deprecated({ + reason: "Use `String.fromCharCodeMany` instead", + migrate: String.fromCharCodeMany(), +}) +@val +@variadic external fromCharCodeMany: array => t = "String.fromCharCode" /** @@ -89,6 +102,10 @@ Js.String2.fromCodePoint(0xd55c) == `한` Js.String2.fromCodePoint(0x1f63a) == `😺` ``` */ +@deprecated({ + reason: "Use `String.fromCodePoint` instead", + migrate: String.fromCodePoint(), +}) @val external fromCodePoint: int => t = "String.fromCodePoint" @@ -106,7 +123,12 @@ on MDN. Js.String2.fromCodePointMany([0xd55c, 0xae00, 0x1f63a]) == `한글😺` ``` */ -@val @variadic +@deprecated({ + reason: "Use `String.fromCodePointMany` instead", + migrate: String.fromCodePointMany(), +}) +@val +@variadic external fromCodePointMany: array => t = "String.fromCodePoint" /* String.raw: ES2015, meant to be used with template strings, not directly */ @@ -123,6 +145,10 @@ on MDN. Js.String2.length("abcd") == 4 ``` */ +@deprecated({ + reason: "Use `String.length` instead", + migrate: String.length(), +}) @get external length: t => int = "length" @@ -139,6 +165,10 @@ Js.String2.get("Reason", 4) == "o" Js.String2.get(`Rẽasöń`, 5) == `ń` ``` */ +@deprecated({ + reason: "Use `String.getUnsafe` instead. Or use `String.get` for a safe version that returns an option.", + migrate: String.getUnsafe(), +}) @get_index external get: (t, int) => t = "" @@ -159,6 +189,10 @@ Js.String2.charAt("Reason", 12) == "" Js.String2.charAt(`Rẽasöń`, 5) == `ń` ``` */ +@deprecated({ + reason: "Use `String.charAt` instead", + migrate: String.charAt(), +}) @send external charAt: (t, int) => t = "charAt" @@ -179,6 +213,10 @@ Js.String2.charCodeAt(`😺`, 0) == 0xd83d->Belt.Int.toFloat Js.String2.codePointAt(`😺`, 0) == Some(0x1f63a) ``` */ +@deprecated({ + reason: "Use `String.charCodeAt` instead", + migrate: String.charCodeAt(), +}) @send external charCodeAt: (t, int) => float = "charCodeAt" @@ -198,6 +236,10 @@ Js.String2.codePointAt(`¿😺?`, 1) == Some(0x1f63a) Js.String2.codePointAt("abc", 5) == None ``` */ +@deprecated({ + reason: "Use `String.codePointAt` instead", + migrate: String.codePointAt(), +}) @send external codePointAt: (t, int) => option = "codePointAt" @@ -214,6 +256,10 @@ on MDN. Js.String2.concat("cow", "bell") == "cowbell" ``` */ +@deprecated({ + reason: "Use `String.concat` instead", + migrate: String.concat(), +}) @send external concat: (t, t) => t = "concat" @@ -230,7 +276,12 @@ on MDN. Js.String2.concatMany("1st", ["2nd", "3rd", "4th"]) == "1st2nd3rd4th" ``` */ -@send @variadic +@deprecated({ + reason: "Use `String.concatMany` instead", + migrate: String.concatMany(), +}) +@send +@variadic external concatMany: (t, array) => t = "concat" /** @@ -247,6 +298,10 @@ Js.String2.endsWith("ReScript", "Script") == true Js.String2.endsWith("C++", "Script") == false ``` */ +@deprecated({ + reason: "Use `String.endsWith` instead", + migrate: String.endsWith(), +}) @send external endsWith: (t, t) => bool = "endsWith" @@ -268,6 +323,10 @@ Js.String2.endsWithFrom("abcde", "cde", 99) == true Js.String2.endsWithFrom("example.dat", "ple", 7) == true ``` */ +@deprecated({ + reason: "Use `String.endsWithFrom` instead", + migrate: String.endsWithFrom(), +}) @send external endsWithFrom: (t, t, int) => bool = "endsWith" @@ -287,6 +346,10 @@ Js.String2.includes("programmer", "pro") == true Js.String2.includes("programmer.dat", "xyz") == false ``` */ +@deprecated({ + reason: "Use `String.includes` instead", + migrate: String.includes(), +}) @send external includes: (t, t) => bool = "includes" @@ -306,6 +369,10 @@ Js.String2.includesFrom("programmer", "gram", 4) == false Js.String2.includesFrom(`대한민국`, `한`, 1) == true ``` */ +@deprecated({ + reason: "Use `String.includesFrom` instead", + migrate: String.includesFrom(), +}) @send external includesFrom: (t, t, int) => bool = "includes" @@ -325,6 +392,10 @@ Js.String2.indexOf("beekeeper", "ee") == 1 Js.String2.indexOf("bookseller", "xyz") == -1 ``` */ +@deprecated({ + reason: "Use `String.indexOf` instead", + migrate: String.indexOf(), +}) @send external indexOf: (t, t) => int = "indexOf" @@ -346,6 +417,10 @@ Js.String2.indexOfFrom("bookseller", "sell", 2) == 4 Js.String2.indexOfFrom("bookseller", "sell", 5) == -1 ``` */ +@deprecated({ + reason: "Use `String.indexOfFrom` instead", + migrate: String.indexOfFrom(), +}) @send external indexOfFrom: (t, t, int) => int = "indexOf" @@ -366,6 +441,10 @@ Js.String2.lastIndexOf("beekeeper", "ee") == 4 Js.String2.lastIndexOf("abcdefg", "xyz") == -1 ``` */ +@deprecated({ + reason: "Use `String.lastIndexOf` instead", + migrate: String.lastIndexOf(), +}) @send external lastIndexOf: (t, t) => int = "lastIndexOf" @@ -387,6 +466,10 @@ Js.String2.lastIndexOfFrom("beekeeper", "ee", 3) == 1 Js.String2.lastIndexOfFrom("abcdefg", "xyz", 4) == -1 ``` */ +@deprecated({ + reason: "Use `String.lastIndexOfFrom` instead", + migrate: String.lastIndexOfFrom(), +}) @send external lastIndexOfFrom: (t, t, int) => int = "lastIndexOf" @@ -409,6 +492,10 @@ Js.String2.localeCompare("cat", "cat") == 0.0 Js.String2.localeCompare("CAT", "cat") > 0.0 ``` */ +@deprecated({ + reason: "Use `String.localeCompare` instead", + migrate: String.localeCompare(), +}) @send external localeCompare: (t, t) => float = "localeCompare" @@ -434,7 +521,12 @@ Js.String2.match_("Today is 2018-04-05.", /(\d+)-(\d+)-(\d+)/) == Js.String2.match_("The large container.", /b[aeiou]g/) == None ``` */ -@send @return({null_to_opt: null_to_opt}) +@deprecated({ + reason: "Use `String.match` instead", + migrate: String.match(), +}) +@send +@return({null_to_opt: null_to_opt}) external match_: (t, Js_re.t) => option>> = "match" /** @@ -448,6 +540,10 @@ See [`String.normalize`](https://developer.mozilla.org/en-US/docs/Web/JavaScript on MDN. See also [Unicode technical report #15](https://unicode.org/reports/tr15/) for details. */ +@deprecated({ + reason: "Use `String.normalize` instead", + migrate: String.normalize(), +}) @send external normalize: t => t = "normalize" @@ -462,6 +558,10 @@ specified form of normalization, which may be one of: See [`String.normalize`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize) on MDN. See also [Unicode technical report #15](https://unicode.org/reports/tr15/) for details. */ +@deprecated({ + reason: "Use `String.normalizeByForm` instead", + migrate: String.normalizeByForm(), +}) @send external normalizeByForm: (t, t) => t = "normalize" @@ -479,6 +579,10 @@ Js.String2.repeat("ha", 3) == "hahaha" Js.String2.repeat("empty", 0) == "" ``` */ +@deprecated({ + reason: "Use `String.repeat` instead", + migrate: String.repeat(), +}) @send external repeat: (t, int) => t = "repeat" @@ -498,6 +602,10 @@ Js.String2.replace("old string", "old", "new") == "new string" Js.String2.replace("the cat and the dog", "the", "this") == "this cat and the dog" ``` */ +@deprecated({ + reason: "Use `String.replace` instead", + migrate: String.replace(), +}) @send external replace: (t, t, t) => t = "replace" @@ -515,6 +623,10 @@ Js.String2.replaceByRe("vowels be gone", /[aeiou]/g, "x") == "vxwxls bx gxnx" Js.String2.replaceByRe("Juan Fulano", /(\w+) (\w+)/, "$2, $1") == "Fulano, Juan" ``` */ +@deprecated({ + reason: "Use `String.replaceRegExp` instead", + migrate: String.replaceRegExp(), +}) @send external replaceByRe: (t, Js_re.t, t) => t = "replace" @@ -537,6 +649,10 @@ let matchFn = (matchPart, _offset, _wholeString) => Js.String2.toUpperCase(match Js.String2.unsafeReplaceBy0(str, re, matchFn) == "bEAUtIfUl vOwEls" ``` */ +@deprecated({ + reason: "Use `String.replaceRegExpBy0Unsafe` instead", + migrate: String.replaceRegExpBy0Unsafe(), +}) @send external unsafeReplaceBy0: (t, Js_re.t, (t, int, t) => t) => t = "replace" @@ -562,6 +678,10 @@ let matchFn = (_match, part1, _offset, _wholeString) => { Js.String2.unsafeReplaceBy1(str, re, matchFn) == "Jony is 41" ``` */ +@deprecated({ + reason: "Use `String.replaceRegExpBy1Unsafe` instead", + migrate: String.replaceRegExpBy1Unsafe(), +}) @send external unsafeReplaceBy1: (t, Js_re.t, (t, t, int, t) => t) => t = "replace" @@ -590,6 +710,10 @@ let matchFn = (_match, p1, p2, _offset, _wholeString) => { Js.String2.unsafeReplaceBy2(str, re, matchFn) == "42" ``` */ +@deprecated({ + reason: "Use `String.replaceRegExpBy2Unsafe` instead", + migrate: String.replaceRegExpBy2Unsafe(), +}) @send external unsafeReplaceBy2: (t, Js_re.t, (t, t, t, int, t) => t) => t = "replace" @@ -603,6 +727,10 @@ matched. See [`String.replace`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace) on MDN. */ +@deprecated({ + reason: "Use `String.replaceRegExpBy3Unsafe` instead", + migrate: String.replaceRegExpBy3Unsafe(), +}) @send external unsafeReplaceBy3: (t, Js_re.t, (t, t, t, t, int, t) => t) => t = "replace" @@ -620,6 +748,10 @@ Js.String2.search("testing 1 2 3", /\d+/) == 8 Js.String2.search("no numbers", /\d+/) == -1 ``` */ +@deprecated({ + reason: "Use `String.search` instead", + migrate: String.search(), +}) @send external search: (t, Js_re.t) => int = "search" @@ -641,6 +773,13 @@ Js.String2.slice("abcdefg", ~from=-4, ~to_=-2) == "de" Js.String2.slice("abcdefg", ~from=5, ~to_=1) == "" ``` */ +@deprecated({ + reason: "Use `String.slice` instead", + migrate: String.slice( + ~start=%insert.labelledArgument("from"), + ~end=%insert.labelledArgument("to_"), + ), +}) @send external slice: (t, ~from: int, ~to_: int) => t = "slice" @@ -660,6 +799,10 @@ Js.String2.sliceToEnd("abcdefg", ~from=-2) == "fg" Js.String2.sliceToEnd("abcdefg", ~from=7) == "" ``` */ +@deprecated({ + reason: "Use `String.sliceToEnd` instead", + migrate: String.sliceToEnd(~start=%insert.labelledArgument("from")), +}) @send external sliceToEnd: (t, ~from: int) => t = "slice" @@ -679,6 +822,10 @@ Js.String2.split("good::bad as great::awful", "::") == ["good", "bad as great", Js.String2.split("has-no-delimiter", ";") == ["has-no-delimiter"] ``` */ +@deprecated({ + reason: "Use `String.split` instead", + migrate: String.split(), +}) @send external split: (t, t) => array = "split" @@ -691,6 +838,10 @@ splitAtMost "ant/bee/cat/dog/elk" "/" ~limit: 0 = [| |];; splitAtMost "ant/bee/cat/dog/elk" "/" ~limit: 9 = [|"ant"; "bee"; "cat"; "dog"; "elk"|];; ``` */ +@deprecated({ + reason: "Use `String.splitAtMost` instead", + migrate: String.splitAtMost(), +}) @send external splitAtMost: (t, t, ~limit: int) => array = "split" @@ -712,6 +863,10 @@ Js.String2.splitByRe("art; bed , cog ;dad", /\s*[,;]\s*TODO/) == [ ] ``` */ +@deprecated({ + reason: "Use `String.splitByRegExp` instead", + migrate: String.splitByRegExp(), +}) @send external splitByRe: (t, Js_re.t) => array> = "split" @@ -743,6 +898,10 @@ Js.String2.splitByReAtMost("one: two: three: four", /\s*:\s*TODO/, ~limit=8) == ] ``` */ +@deprecated({ + reason: "Use `String.splitByRegExpAtMost` instead", + migrate: String.splitByRegExpAtMost(), +}) @send external splitByReAtMost: (t, Js_re.t, ~limit: int) => array> = "split" @@ -761,6 +920,10 @@ Js.String2.startsWith("ReScript", "") == true Js.String2.startsWith("JavaScript", "Re") == false ``` */ +@deprecated({ + reason: "Use `String.startsWith` instead", + migrate: String.startsWith(), +}) @send external startsWith: (t, t) => bool = "startsWith" @@ -780,6 +943,10 @@ Js.String2.startsWithFrom("ReScript", "", 2) == true Js.String2.startsWithFrom("JavaScript", "Scri", 2) == false ``` */ +@deprecated({ + reason: "Use `String.startsWithFrom` instead", + migrate: String.startsWithFrom(), +}) @send external startsWithFrom: (t, t, int) => bool = "startsWith" @@ -803,7 +970,7 @@ Js.String2.substr("abcdefghij", ~from=-3) == "hij" Js.String2.substr("abcdefghij", ~from=12) == "" ``` */ -@send +@deprecated("Use `String.substring` instead") @send external substr: (t, ~from: int) => t = "substr" /** @@ -827,7 +994,7 @@ Js.String2.substrAtMost("abcdefghij", ~from=-3, ~length=4) == "hij" Js.String2.substrAtMost("abcdefghij", ~from=12, ~length=2) == "" ``` */ -@send +@deprecated("Use `String.substringAtMost` instead") @send external substrAtMost: (t, ~from: int, ~length: int) => t = "substr" /** @@ -847,6 +1014,13 @@ Js.String2.substring("playground", ~from=6, ~to_=3) == "ygr" Js.String2.substring("playground", ~from=4, ~to_=12) == "ground" ``` */ +@deprecated({ + reason: "Use `String.substring` instead", + migrate: String.substring( + ~start=%insert.labelledArgument("from"), + ~end=%insert.labelledArgument("to_"), + ), +}) @send external substring: (t, ~from: int, ~to_: int) => t = "substring" @@ -866,6 +1040,10 @@ Js.String2.substringToEnd("playground", ~from=-3) == "playground" Js.String2.substringToEnd("playground", ~from=12) == "" ``` */ +@deprecated({ + reason: "Use `String.substringToEnd` instead", + migrate: String.substringToEnd(~start=%insert.labelledArgument("from")), +}) @send external substringToEnd: (t, ~from: int) => t = "substring" @@ -887,6 +1065,10 @@ Js.String2.toLowerCase(`ΣΠ`) == `σπ` Js.String2.toLowerCase(`ΠΣ`) == `πς` ``` */ +@deprecated({ + reason: "Use `String.toLowerCase` instead", + migrate: String.toLowerCase(), +}) @send external toLowerCase: t => t = "toLowerCase" @@ -895,6 +1077,10 @@ external toLowerCase: t => t = "toLowerCase" See [`String.toLocaleLowerCase`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toLocaleLowerCase) on MDN. */ +@deprecated({ + reason: "Use `String.toLocaleLowerCase` instead", + migrate: String.toLocaleLowerCase(), +}) @send external toLocaleLowerCase: t => t = "toLocaleLowerCase" @@ -915,6 +1101,10 @@ Js.String2.toUpperCase(`Straße`) == `STRASSE` Js.String2.toUpperCase(`πς`) == `ΠΣ` ``` */ +@deprecated({ + reason: "Use `String.toUpperCase` instead", + migrate: String.toUpperCase(), +}) @send external toUpperCase: t => t = "toUpperCase" @@ -923,6 +1113,10 @@ external toUpperCase: t => t = "toUpperCase" See [`String.to:LocaleUpperCase`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toLocaleUpperCase) on MDN. */ +@deprecated({ + reason: "Use `String.toLocaleUpperCase` instead", + migrate: String.toLocaleUpperCase(), +}) @send external toLocaleUpperCase: t => t = "toLocaleUpperCase" @@ -940,6 +1134,10 @@ Js.String2.trim(" abc def ") == "abc def" Js.String2.trim("\n\r\t abc def \n\n\t\r ") == "abc def" ``` */ +@deprecated({ + reason: "Use `String.trim` instead", + migrate: String.trim(), +}) @send external trim: t => t = "trim" @@ -959,7 +1157,7 @@ on MDN. Js.String2.anchor("Page One", "page1") == "Page One" ``` */ -@send +@deprecated("This function has been removed from the relevant web standards.") @send external anchor: (t, t) => t = "anchor" /** @@ -975,7 +1173,7 @@ on MDN. Js.String2.link("Go to page two", "page2.html") == "Go to page two" ``` */ -@send +@deprecated("This function has been removed from the relevant web standards.") @send external link: (t, t) => t = "link" /* FIXME: we should not encourage people to use [%identity], better @@ -994,4 +1192,8 @@ let arr = Js.Array2.fromMap(Js.String2.castToArrayLike(s), x => x) arr == ["a", "b", "c", "d", "e"] ``` */ +@deprecated({ + reason: "Use `Array.fromString` instead", + migrate: Array.fromString(), +}) external castToArrayLike: t => Js_array2.array_like = "%identity" diff --git a/runtime/Stdlib_Array.res b/runtime/Stdlib_Array.res index 32a9979b8f..c5e40bedf8 100644 --- a/runtime/Stdlib_Array.res +++ b/runtime/Stdlib_Array.res @@ -13,6 +13,8 @@ external unsafe_get: (array<'a>, int) => 'a = "%array_unsafe_get" @val external fromArrayLikeWithMap: (arrayLike<'a>, 'a => 'b) => array<'b> = "Array.from" +@val external fromString: string => array = "Array.from" + @send external fillAll: (array<'a>, 'a) => unit = "fill" @send external fillToEnd: (array<'a>, 'a, ~start: int) => unit = "fill" diff --git a/runtime/Stdlib_Array.resi b/runtime/Stdlib_Array.resi index 8eb31682b4..825c65eea8 100644 --- a/runtime/Stdlib_Array.resi +++ b/runtime/Stdlib_Array.resi @@ -31,6 +31,17 @@ external fromIterator: Stdlib_Iterator.t<'a> => array<'a> = "Array.from" @val external fromArrayLikeWithMap: (arrayLike<'a>, 'a => 'b) => array<'b> = "Array.from" +/** +`fromString(str)` creates an array of each character as a separate string from the provided `str`. + +## Examples + +```rescript +Array.fromString("abcde") == ["a", "b", "c", "d", "e"] +``` +*/ +@val external fromString: string => array = "Array.from" + /** `make(~length, init)` creates an array of length `length` initialized with the value of `init`. @@ -80,14 +91,56 @@ someArray->Array.length == 2 @get external length: array<'a> => int = "length" -// TODO: Docs +/** +`copyAllWithin(array, ~target)` copies from the first element in the given array to the designated `target` position, returning the resulting array. + +Beware this will *mutate* the array. + +See [`Array.copyWithin`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin) on MDN. + +## Examples + +```rescript +let arr = [100, 101, 102, 103, 104] +arr->Array.copyAllWithin(~target=2) == [100, 101, 100, 101, 102] +arr == [100, 101, 100, 101, 102] +``` +*/ @send external copyAllWithin: (array<'a>, ~target: int) => array<'a> = "copyWithin" -// TODO: Docs +/** +`copyWithinToEnd(array, ~target, ~start)` copies starting at element `start` in the given array to the designated `target` position, returning the resulting array. + +Beware this will *mutate* the array. + +See [`Array.copyWithin`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin) on MDN. + +## Examples + +```rescript +let arr = [100, 101, 102, 103, 104] +arr->Array.copyWithinToEnd(~target=0, ~start=2) == [102, 103, 104, 103, 104] +arr == [102, 103, 104, 103, 104] +``` +*/ @send external copyWithinToEnd: (array<'a>, ~target: int, ~start: int) => array<'a> = "copyWithin" -// TODO: Docs +/** +`copyWithin(array, ~target, ~start, ~end)` copies starting at element `start` in the given array up to but not including `end` to the designated `target` position, returning the resulting array. + +Beware this will *mutate* the array. + +See [`Array.copyWithin`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin) on MDN. + +## Examples + +```rescript +let arr = [100, 101, 102, 103, 104, 105] +arr->Array.copyWithin(~target=1, ~start=2, ~end=5) == [100, 102, 103, 104, 104, 105] +arr == [100, 102, 103, 104, 104, 105] +``` +*/ @send external copyWithin: (array<'a>, ~target: int, ~start: int, ~end: int) => array<'a> = "copyWithin" diff --git a/runtime/Stdlib_BigInt.resi b/runtime/Stdlib_BigInt.resi index 41d8421ad5..690307f96b 100644 --- a/runtime/Stdlib_BigInt.resi +++ b/runtime/Stdlib_BigInt.resi @@ -80,7 +80,11 @@ BigInt.fromString("invalid") == None */ let fromString: string => option -@deprecated("Use `fromStringOrThrow` instead") @val +@deprecated({ + reason: "Use `fromStringOrThrow` instead", + migrate: BigInt.fromStringOrThrow(), +}) +@val external fromStringExn: string => bigint = "BigInt" /** @@ -147,7 +151,11 @@ BigInt.toString(123n) == "123" @send external toString: (bigint, ~radix: int=?) => string = "toString" -@deprecated("Use `toString` with `~radix` instead") @send +@deprecated({ + reason: "Use `toString` with `~radix` instead", + migrate: BigInt.toString(), +}) +@send external toStringWithRadix: (bigint, ~radix: int) => string = "toString" /** @@ -339,7 +347,11 @@ external ignore: bigint => unit = "%ignore" BigInt.land(7n, 4n) == 4n ``` */ -@deprecated("Use `&` operator or `bitwiseAnd` instead.") +@deprecated({ + reason: "Use `&` operator or `bitwiseAnd` instead.", + migrate: %insert.unlabelledArgument(0) & %insert.unlabelledArgument(1), + migratePiped: BigInt.bitwiseAnd(), +}) external land: (bigint, bigint) => bigint = "%andbigint" /** @@ -353,7 +365,10 @@ external land: (bigint, bigint) => bigint = "%andbigint" BigInt.lor(7n, 4n) == 7n ``` */ -@deprecated("Use `bitwiseOr` instead.") +@deprecated({ + reason: "Use `bitwiseOr` instead.", + migrate: BigInt.bitwiseOr(), +}) external lor: (bigint, bigint) => bigint = "%orbigint" /** @@ -367,7 +382,11 @@ external lor: (bigint, bigint) => bigint = "%orbigint" BigInt.lxor(7n, 4n) == 3n ``` */ -@deprecated("Use `^` operator or `bitwiseXor` instead.") +@deprecated({ + reason: "Use `^` operator or `bitwiseXor` instead.", + migrate: %insert.unlabelledArgument(0) ^ %insert.unlabelledArgument(1), + migratePiped: BigInt.bitwiseXor(), +}) external lxor: (bigint, bigint) => bigint = "%xorbigint" /** @@ -381,7 +400,11 @@ external lxor: (bigint, bigint) => bigint = "%xorbigint" BigInt.lnot(2n) == -3n ``` */ -@deprecated("Use `~` operator or `bitwiseNot` instead.") +@deprecated({ + reason: "Use `~` operator or `bitwiseNot` instead.", + migrate: ~(%insert.unlabelledArgument(0)), + migratePiped: BigInt.bitwiseNot(), +}) external lnot: bigint => bigint = "%bitnot_bigint" /** @@ -395,7 +418,11 @@ external lnot: bigint => bigint = "%bitnot_bigint" BigInt.lsl(4n, 1n) == 8n ``` */ -@deprecated("Use `<<` operator or `shiftLeft` instead.") +@deprecated({ + reason: "Use `<<` operator or `shiftLeft` instead.", + migrate: %insert.unlabelledArgument(0) << %insert.unlabelledArgument(1), + migratePiped: BigInt.shiftLeft(), +}) external lsl: (bigint, bigint) => bigint = "%lslbigint" /** @@ -409,5 +436,9 @@ external lsl: (bigint, bigint) => bigint = "%lslbigint" BigInt.asr(8n, 1n) == 4n ``` */ -@deprecated("Use `>>` operator or `shiftRight` instead.") +@deprecated({ + reason: "Use `>>` operator or `shiftRight` instead.", + migrate: %insert.unlabelledArgument(0) >> %insert.unlabelledArgument(1), + migratePiped: BigInt.shiftRight(), +}) external asr: (bigint, bigint) => bigint = "%asrbigint" diff --git a/runtime/Stdlib_Int.res b/runtime/Stdlib_Int.res index 3228ed4114..cef0ee6b27 100644 --- a/runtime/Stdlib_Int.res +++ b/runtime/Stdlib_Int.res @@ -105,6 +105,18 @@ external shiftLeft: (int, int) => int = "%lslint" external shiftRight: (int, int) => int = "%asrint" external shiftRightUnsigned: (int, int) => int = "%lsrint" +module Bitwise = { + external land: (int, int) => int = "%andint" + external lor: (int, int) => int = "%orint" + external lxor: (int, int) => int = "%xorint" + + external lsl: (int, int) => int = "%lslint" + external lsr: (int, int) => int = "%lsrint" + external asr: (int, int) => int = "%asrint" + + let lnot = x => lxor(x, -1) +} + external ignore: int => unit = "%ignore" module Ref = { diff --git a/runtime/Stdlib_Int.resi b/runtime/Stdlib_Int.resi index 384e351287..9959990901 100644 --- a/runtime/Stdlib_Int.resi +++ b/runtime/Stdlib_Int.resi @@ -186,7 +186,6 @@ Int.toPrecisionWithPrecision(1, ~digits=2) // "1.0" - `RangeError`: If `digits` is not between 1 and 100 (inclusive). Implementations are allowed to support larger and smaller values as well. ECMA-262 only requires a precision of up to 21 significant digits. - */ @send @deprecated("Use `toPrecision` instead") external toPrecisionWithPrecision: (int, ~digits: int) => string = "toPrecision" @@ -471,6 +470,46 @@ Int.shiftRightUnsigned(4, 1) == 2 */ external shiftRightUnsigned: (int, int) => int = "%lsrint" +module Bitwise: { + @deprecated({ + reason: "Use `Int.bitwiseAnd` instead", + migrate: Int.bitwiseAnd(), + }) + external land: (int, int) => int = "%andint" + @deprecated({ + reason: "Use `Int.bitwiseOr` instead", + migrate: Int.bitwiseOr(), + }) + external lor: (int, int) => int = "%orint" + @deprecated({ + reason: "Use `Int.bitwiseXor` instead", + migrate: Int.bitwiseXor(), + }) + external lxor: (int, int) => int = "%xorint" + + @deprecated({ + reason: "Use `Int.shiftLeft` instead", + migrate: Int.shiftLeft(), + }) + external lsl: (int, int) => int = "%lslint" + @deprecated({ + reason: "Use `Int.shiftRightUnsigned` instead", + migrate: Int.shiftRightUnsigned(), + }) + external lsr: (int, int) => int = "%lsrint" + @deprecated({ + reason: "Use `Int.shiftRight` instead", + migrate: Int.shiftRight(), + }) + external asr: (int, int) => int = "%asrint" + + @deprecated({ + reason: "Use `Int.bitwiseNot` instead", + migrate: Int.bitwiseNot(), + }) + let lnot: int => int +} + /** `ignore(int)` ignores the provided int and returns unit. diff --git a/runtime/Stdlib_String.resi b/runtime/Stdlib_String.resi index 896bf1dc4b..0d0b472d9b 100644 --- a/runtime/Stdlib_String.resi +++ b/runtime/Stdlib_String.resi @@ -1070,7 +1070,7 @@ String.trimStart(" Hello world! ") == "Hello world! " external trimStart: string => string = "trimStart" /** -`trinEnd(str)` returns a string that is `str` with whitespace stripped from the +`trimEnd(str)` returns a string that is `str` with whitespace stripped from the end of a string. Internal whitespace is not removed. See [`String.trimEnd`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trimEnd) on MDN. diff --git a/tests/analysis_tests/tests/src/expected/Completion.res.txt b/tests/analysis_tests/tests/src/expected/Completion.res.txt index 0663346ce6..f1e8b81926 100644 --- a/tests/analysis_tests/tests/src/expected/Completion.res.txt +++ b/tests/analysis_tests/tests/src/expected/Completion.res.txt @@ -285,7 +285,7 @@ Path Array. "kind": 12, "tags": [], "detail": "(\n array<'a>,\n ~target: int,\n ~start: int,\n ~end: int,\n) => array<'a>", - "documentation": null + "documentation": {"kind": "markdown", "value": "\n`copyWithin(array, ~target, ~start, ~end)` copies starting at element `start` in the given array up to but not including `end` to the designated `target` position, returning the resulting array.\n\nBeware this will *mutate* the array.\n\nSee [`Array.copyWithin`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin) on MDN.\n\n## Examples\n\n```rescript\nlet arr = [100, 101, 102, 103, 104, 105]\narr->Array.copyWithin(~target=1, ~start=2, ~end=5) == [100, 102, 103, 104, 104, 105]\narr == [100, 102, 103, 104, 104, 105]\n```\n"} }, { "label": "toString", "kind": 12, @@ -316,6 +316,12 @@ Path Array. "tags": [], "detail": "array<'a> => unit", "documentation": {"kind": "markdown", "value": "\n`reverse(array)` reverses the order of the items in `array`.\n\nBeware this will *mutate* the array.\n\nSee [`Array.reverse`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse) on MDN.\n\n## Examples\n\n```rescript\nlet someArray = [\"hi\", \"hello\"]\nsomeArray->Array.reverse\n\nsomeArray == [\"hello\", \"hi\"]\n```\n"} + }, { + "label": "fromString", + "kind": 12, + "tags": [], + "detail": "string => array", + "documentation": {"kind": "markdown", "value": "\n`fromString(str)` creates an array of each character as a separate string from the provided `str`.\n\n## Examples\n\n```rescript\nArray.fromString(\"abcde\") == [\"a\", \"b\", \"c\", \"d\", \"e\"]\n```\n"} }, { "label": "findLastIndexWithIndex", "kind": 12, @@ -477,7 +483,7 @@ Path Array. "kind": 12, "tags": [], "detail": "(array<'a>, ~target: int, ~start: int) => array<'a>", - "documentation": null + "documentation": {"kind": "markdown", "value": "\n`copyWithinToEnd(array, ~target, ~start)` copies starting at element `start` in the given array to the designated `target` position, returning the resulting array.\n\nBeware this will *mutate* the array.\n\nSee [`Array.copyWithin`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin) on MDN.\n\n## Examples\n\n```rescript\nlet arr = [100, 101, 102, 103, 104]\narr->Array.copyWithinToEnd(~target=0, ~start=2) == [102, 103, 104, 103, 104]\narr == [102, 103, 104, 103, 104]\n```\n"} }, { "label": "unshift", "kind": 12, @@ -525,7 +531,7 @@ Path Array. "kind": 12, "tags": [], "detail": "(array<'a>, ~target: int) => array<'a>", - "documentation": null + "documentation": {"kind": "markdown", "value": "\n`copyAllWithin(array, ~target)` copies from the first element in the given array to the designated `target` position, returning the resulting array.\n\nBeware this will *mutate* the array.\n\nSee [`Array.copyWithin`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin) on MDN.\n\n## Examples\n\n```rescript\nlet arr = [100, 101, 102, 103, 104]\narr->Array.copyAllWithin(~target=2) == [100, 101, 100, 101, 102]\narr == [100, 101, 100, 101, 102]\n```\n"} }, { "label": "keepSome", "kind": 12, @@ -2471,7 +2477,7 @@ Path t "kind": 12, "tags": [1], "detail": "(int, ~digits: int) => string", - "documentation": {"kind": "markdown", "value": "Deprecated: Use `toPrecision` instead\n\n\n`toPrecisionWithPrecision(n, ~digits)` return a `string` representing the giver value with\nprecision. `digits` specifies the number of significant digits. See [`Number.toPrecision`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toPrecision) on MDN.\n\n## Examples\n\n```rescript\nInt.toPrecisionWithPrecision(100, ~digits=2) // \"1.0e+2\"\nInt.toPrecisionWithPrecision(1, ~digits=2) // \"1.0\"\n```\n\n## Exceptions\n\n- `RangeError`: If `digits` is not between 1 and 100 (inclusive).\n Implementations are allowed to support larger and smaller values as well.\n ECMA-262 only requires a precision of up to 21 significant digits.\n \n"} + "documentation": {"kind": "markdown", "value": "Deprecated: Use `toPrecision` instead\n\n\n`toPrecisionWithPrecision(n, ~digits)` return a `string` representing the giver value with\nprecision. `digits` specifies the number of significant digits. See [`Number.toPrecision`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toPrecision) on MDN.\n\n## Examples\n\n```rescript\nInt.toPrecisionWithPrecision(100, ~digits=2) // \"1.0e+2\"\nInt.toPrecisionWithPrecision(1, ~digits=2) // \"1.0\"\n```\n\n## Exceptions\n\n- `RangeError`: If `digits` is not between 1 and 100 (inclusive).\n Implementations are allowed to support larger and smaller values as well.\n ECMA-262 only requires a precision of up to 21 significant digits.\n"} }, { "label": "Int.toPrecision", "kind": 12, diff --git a/tests/analysis_tests/tests/src/expected/CompletionInferValues.res.txt b/tests/analysis_tests/tests/src/expected/CompletionInferValues.res.txt index dc885d8485..cbc06886c9 100644 --- a/tests/analysis_tests/tests/src/expected/CompletionInferValues.res.txt +++ b/tests/analysis_tests/tests/src/expected/CompletionInferValues.res.txt @@ -34,7 +34,7 @@ Path t "kind": 12, "tags": [1], "detail": "(int, ~digits: int) => string", - "documentation": {"kind": "markdown", "value": "Deprecated: Use `toPrecision` instead\n\n\n`toPrecisionWithPrecision(n, ~digits)` return a `string` representing the giver value with\nprecision. `digits` specifies the number of significant digits. See [`Number.toPrecision`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toPrecision) on MDN.\n\n## Examples\n\n```rescript\nInt.toPrecisionWithPrecision(100, ~digits=2) // \"1.0e+2\"\nInt.toPrecisionWithPrecision(1, ~digits=2) // \"1.0\"\n```\n\n## Exceptions\n\n- `RangeError`: If `digits` is not between 1 and 100 (inclusive).\n Implementations are allowed to support larger and smaller values as well.\n ECMA-262 only requires a precision of up to 21 significant digits.\n \n"} + "documentation": {"kind": "markdown", "value": "Deprecated: Use `toPrecision` instead\n\n\n`toPrecisionWithPrecision(n, ~digits)` return a `string` representing the giver value with\nprecision. `digits` specifies the number of significant digits. See [`Number.toPrecision`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toPrecision) on MDN.\n\n## Examples\n\n```rescript\nInt.toPrecisionWithPrecision(100, ~digits=2) // \"1.0e+2\"\nInt.toPrecisionWithPrecision(1, ~digits=2) // \"1.0\"\n```\n\n## Exceptions\n\n- `RangeError`: If `digits` is not between 1 and 100 (inclusive).\n Implementations are allowed to support larger and smaller values as well.\n ECMA-262 only requires a precision of up to 21 significant digits.\n"} }, { "label": "Int.toPrecision", "kind": 12, @@ -352,7 +352,7 @@ Path t "kind": 12, "tags": [1], "detail": "(int, ~digits: int) => string", - "documentation": {"kind": "markdown", "value": "Deprecated: Use `toPrecision` instead\n\n\n`toPrecisionWithPrecision(n, ~digits)` return a `string` representing the giver value with\nprecision. `digits` specifies the number of significant digits. See [`Number.toPrecision`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toPrecision) on MDN.\n\n## Examples\n\n```rescript\nInt.toPrecisionWithPrecision(100, ~digits=2) // \"1.0e+2\"\nInt.toPrecisionWithPrecision(1, ~digits=2) // \"1.0\"\n```\n\n## Exceptions\n\n- `RangeError`: If `digits` is not between 1 and 100 (inclusive).\n Implementations are allowed to support larger and smaller values as well.\n ECMA-262 only requires a precision of up to 21 significant digits.\n \n"} + "documentation": {"kind": "markdown", "value": "Deprecated: Use `toPrecision` instead\n\n\n`toPrecisionWithPrecision(n, ~digits)` return a `string` representing the giver value with\nprecision. `digits` specifies the number of significant digits. See [`Number.toPrecision`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toPrecision) on MDN.\n\n## Examples\n\n```rescript\nInt.toPrecisionWithPrecision(100, ~digits=2) // \"1.0e+2\"\nInt.toPrecisionWithPrecision(1, ~digits=2) // \"1.0\"\n```\n\n## Exceptions\n\n- `RangeError`: If `digits` is not between 1 and 100 (inclusive).\n Implementations are allowed to support larger and smaller values as well.\n ECMA-262 only requires a precision of up to 21 significant digits.\n"} }, { "label": "Int.toPrecision", "kind": 12, diff --git a/tests/analysis_tests/tests/src/expected/CompletionJsx.res.txt b/tests/analysis_tests/tests/src/expected/CompletionJsx.res.txt index e9907b0a2b..3251ada81d 100644 --- a/tests/analysis_tests/tests/src/expected/CompletionJsx.res.txt +++ b/tests/analysis_tests/tests/src/expected/CompletionJsx.res.txt @@ -243,7 +243,7 @@ Path "kind": 12, "tags": [1], "detail": "(int, ~digits: int) => string", - "documentation": {"kind": "markdown", "value": "Deprecated: Use `toPrecision` instead\n\n\n`toPrecisionWithPrecision(n, ~digits)` return a `string` representing the giver value with\nprecision. `digits` specifies the number of significant digits. See [`Number.toPrecision`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toPrecision) on MDN.\n\n## Examples\n\n```rescript\nInt.toPrecisionWithPrecision(100, ~digits=2) // \"1.0e+2\"\nInt.toPrecisionWithPrecision(1, ~digits=2) // \"1.0\"\n```\n\n## Exceptions\n\n- `RangeError`: If `digits` is not between 1 and 100 (inclusive).\n Implementations are allowed to support larger and smaller values as well.\n ECMA-262 only requires a precision of up to 21 significant digits.\n \n"} + "documentation": {"kind": "markdown", "value": "Deprecated: Use `toPrecision` instead\n\n\n`toPrecisionWithPrecision(n, ~digits)` return a `string` representing the giver value with\nprecision. `digits` specifies the number of significant digits. See [`Number.toPrecision`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toPrecision) on MDN.\n\n## Examples\n\n```rescript\nInt.toPrecisionWithPrecision(100, ~digits=2) // \"1.0e+2\"\nInt.toPrecisionWithPrecision(1, ~digits=2) // \"1.0\"\n```\n\n## Exceptions\n\n- `RangeError`: If `digits` is not between 1 and 100 (inclusive).\n Implementations are allowed to support larger and smaller values as well.\n ECMA-262 only requires a precision of up to 21 significant digits.\n"} }, { "label": "Int.bitwiseAnd", "kind": 12, @@ -413,7 +413,7 @@ Path "kind": 12, "tags": [1], "detail": "(int, ~digits: int) => string", - "documentation": {"kind": "markdown", "value": "Deprecated: Use `toPrecision` instead\n\n\n`toPrecisionWithPrecision(n, ~digits)` return a `string` representing the giver value with\nprecision. `digits` specifies the number of significant digits. See [`Number.toPrecision`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toPrecision) on MDN.\n\n## Examples\n\n```rescript\nInt.toPrecisionWithPrecision(100, ~digits=2) // \"1.0e+2\"\nInt.toPrecisionWithPrecision(1, ~digits=2) // \"1.0\"\n```\n\n## Exceptions\n\n- `RangeError`: If `digits` is not between 1 and 100 (inclusive).\n Implementations are allowed to support larger and smaller values as well.\n ECMA-262 only requires a precision of up to 21 significant digits.\n \n"} + "documentation": {"kind": "markdown", "value": "Deprecated: Use `toPrecision` instead\n\n\n`toPrecisionWithPrecision(n, ~digits)` return a `string` representing the giver value with\nprecision. `digits` specifies the number of significant digits. See [`Number.toPrecision`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toPrecision) on MDN.\n\n## Examples\n\n```rescript\nInt.toPrecisionWithPrecision(100, ~digits=2) // \"1.0e+2\"\nInt.toPrecisionWithPrecision(1, ~digits=2) // \"1.0\"\n```\n\n## Exceptions\n\n- `RangeError`: If `digits` is not between 1 and 100 (inclusive).\n Implementations are allowed to support larger and smaller values as well.\n ECMA-262 only requires a precision of up to 21 significant digits.\n"} }, { "label": "Int.bitwiseAnd", "kind": 12, diff --git a/tests/analysis_tests/tests/src/expected/CompletionPipeChain.res.txt b/tests/analysis_tests/tests/src/expected/CompletionPipeChain.res.txt index 4fb8e0849f..1519636e45 100644 --- a/tests/analysis_tests/tests/src/expected/CompletionPipeChain.res.txt +++ b/tests/analysis_tests/tests/src/expected/CompletionPipeChain.res.txt @@ -347,7 +347,7 @@ Path t "kind": 12, "tags": [1], "detail": "(int, ~digits: int) => string", - "documentation": {"kind": "markdown", "value": "Deprecated: Use `toPrecision` instead\n\n\n`toPrecisionWithPrecision(n, ~digits)` return a `string` representing the giver value with\nprecision. `digits` specifies the number of significant digits. See [`Number.toPrecision`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toPrecision) on MDN.\n\n## Examples\n\n```rescript\nInt.toPrecisionWithPrecision(100, ~digits=2) // \"1.0e+2\"\nInt.toPrecisionWithPrecision(1, ~digits=2) // \"1.0\"\n```\n\n## Exceptions\n\n- `RangeError`: If `digits` is not between 1 and 100 (inclusive).\n Implementations are allowed to support larger and smaller values as well.\n ECMA-262 only requires a precision of up to 21 significant digits.\n \n"} + "documentation": {"kind": "markdown", "value": "Deprecated: Use `toPrecision` instead\n\n\n`toPrecisionWithPrecision(n, ~digits)` return a `string` representing the giver value with\nprecision. `digits` specifies the number of significant digits. See [`Number.toPrecision`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toPrecision) on MDN.\n\n## Examples\n\n```rescript\nInt.toPrecisionWithPrecision(100, ~digits=2) // \"1.0e+2\"\nInt.toPrecisionWithPrecision(1, ~digits=2) // \"1.0\"\n```\n\n## Exceptions\n\n- `RangeError`: If `digits` is not between 1 and 100 (inclusive).\n Implementations are allowed to support larger and smaller values as well.\n ECMA-262 only requires a precision of up to 21 significant digits.\n"} }, { "label": "Int.toPrecision", "kind": 12, diff --git a/tests/build_tests/super_errors/expected/warnings4.res.expected b/tests/build_tests/super_errors/expected/warnings4.res.expected index 0e45f5b371..9eec05e9d6 100644 --- a/tests/build_tests/super_errors/expected/warnings4.res.expected +++ b/tests/build_tests/super_errors/expected/warnings4.res.expected @@ -5,7 +5,7 @@ 9 │ @val external x: myType = "myVariable" 10 │ 11 │ switch x { - 12 │ | #first => Js.log("first") + 12 │ | #first => Console.log("first") 13 │ } 14 │ diff --git a/tests/build_tests/super_errors/expected/warnings5.res.expected b/tests/build_tests/super_errors/expected/warnings5.res.expected index 204f9f1608..23302e6c3f 100644 --- a/tests/build_tests/super_errors/expected/warnings5.res.expected +++ b/tests/build_tests/super_errors/expected/warnings5.res.expected @@ -4,7 +4,7 @@ 10 │ 11 │ switch y { - 12 │ | {otherValue: false} => Js.log("first") + 12 │ | {otherValue: false} => Console.log("first") 13 │ } 14 │ @@ -18,7 +18,7 @@ Either bind these labels explicitly or add ', _' to the pattern. 9 │ @val external y: someRecord = "otherVariable" 10 │ 11 │ switch y { - 12 │ | {otherValue: false} => Js.log("first") + 12 │ | {otherValue: false} => Console.log("first") 13 │ } 14 │ 15 │ switch y { @@ -32,7 +32,7 @@ Either bind these labels explicitly or add ', _' to the pattern. 14 │ 15 │ switch y { - 16 │ | {typ: WithPayload(true)} => Js.log("first") + 16 │ | {typ: WithPayload(true)} => Console.log("first") 17 │ } 18 │ @@ -46,7 +46,7 @@ Either bind these labels explicitly or add ', _' to the pattern. 13 │ } 14 │ 15 │ switch y { - 16 │ | {typ: WithPayload(true)} => Js.log("first") + 16 │ | {typ: WithPayload(true)} => Console.log("first") 17 │ } 18 │ 19 │ let arr = [1] @@ -62,7 +62,7 @@ Either bind these labels explicitly or add ', _' to the pattern. 19 │ let arr = [1] 20 │ 21 │ switch arr { - 22 │ | [] => Js.log("") + 22 │ | [] => Console.log("") 23 │ } 24 │ 25 │ switch arr { @@ -77,7 +77,7 @@ Either bind these labels explicitly or add ', _' to the pattern. 23 │ } 24 │ 25 │ switch arr { - 26 │ | [one] => Js.log(one) + 26 │ | [one] => Console.log(one) 27 │ } 28 │ 29 │ switch arr { diff --git a/tests/build_tests/super_errors/fixtures/curry_in_uncurry.res b/tests/build_tests/super_errors/fixtures/curry_in_uncurry.res index 0c0c3b67e1..92e656deef 100644 --- a/tests/build_tests/super_errors/fixtures/curry_in_uncurry.res +++ b/tests/build_tests/super_errors/fixtures/curry_in_uncurry.res @@ -1,3 +1,3 @@ let f = (a, b) => a + b -f(2, 2)->Js.log +f(2, 2)->Console.log diff --git a/tests/build_tests/super_errors/fixtures/polyvariant_constructors_mismatch_second.res b/tests/build_tests/super_errors/fixtures/polyvariant_constructors_mismatch_second.res index d8eace4719..11299b95c3 100644 --- a/tests/build_tests/super_errors/fixtures/polyvariant_constructors_mismatch_second.res +++ b/tests/build_tests/super_errors/fixtures/polyvariant_constructors_mismatch_second.res @@ -1,7 +1,7 @@ let handle = (ev: [#Click | #KeyDown]) => switch ev { - | #Click => Js.log("clicked") - | #KeyDown => Js.log("key down") + | #Click => Console.log("clicked") + | #KeyDown => Console.log("key down") } let _ = handle(#Resize) diff --git a/tests/build_tests/super_errors/fixtures/todo_with_no_payload.res b/tests/build_tests/super_errors/fixtures/todo_with_no_payload.res index d7aa60688c..e6ef3d533f 100644 --- a/tests/build_tests/super_errors/fixtures/todo_with_no_payload.res +++ b/tests/build_tests/super_errors/fixtures/todo_with_no_payload.res @@ -2,4 +2,4 @@ let implementMeLater = (): string => %todo let x = implementMeLater() -Js.log(x->Js.String2.includes("x")) +Console.log(x->String.includes("x")) diff --git a/tests/build_tests/super_errors/fixtures/todo_with_payload.res b/tests/build_tests/super_errors/fixtures/todo_with_payload.res index a52d80d5c1..d13d745dc7 100644 --- a/tests/build_tests/super_errors/fixtures/todo_with_payload.res +++ b/tests/build_tests/super_errors/fixtures/todo_with_payload.res @@ -2,4 +2,4 @@ let implementMeLater = (): string => %todo("This should return a string eventual let x = implementMeLater() -Js.log(x->Js.String2.includes("x")) +Console.log(x->String.includes("x")) diff --git a/tests/build_tests/super_errors/fixtures/warnings4.res b/tests/build_tests/super_errors/fixtures/warnings4.res index 3c65caefe2..94de143aa1 100644 --- a/tests/build_tests/super_errors/fixtures/warnings4.res +++ b/tests/build_tests/super_errors/fixtures/warnings4.res @@ -9,5 +9,5 @@ type myType = [ @val external x: myType = "myVariable" switch x { -| #first => Js.log("first") +| #first => Console.log("first") } diff --git a/tests/build_tests/super_errors/fixtures/warnings5.res b/tests/build_tests/super_errors/fixtures/warnings5.res index 9e69c5076d..a3739d03b6 100644 --- a/tests/build_tests/super_errors/fixtures/warnings5.res +++ b/tests/build_tests/super_errors/fixtures/warnings5.res @@ -9,21 +9,21 @@ type someRecord = { @val external y: someRecord = "otherVariable" switch y { -| {otherValue: false} => Js.log("first") +| {otherValue: false} => Console.log("first") } switch y { -| {typ: WithPayload(true)} => Js.log("first") +| {typ: WithPayload(true)} => Console.log("first") } let arr = [1] switch arr { -| [] => Js.log("") +| [] => Console.log("") } switch arr { -| [one] => Js.log(one) +| [one] => Console.log(one) } switch arr { diff --git a/tests/tools_tests/Makefile b/tests/tools_tests/Makefile index 4d26df85bb..e8d2c1f3fc 100644 --- a/tests/tools_tests/Makefile +++ b/tests/tools_tests/Makefile @@ -5,6 +5,7 @@ build: test: build ./test.sh + yarn build clean: yarn clean diff --git a/tests/tools_tests/package.json b/tests/tools_tests/package.json index 2bf38e72e8..63fd369df9 100644 --- a/tests/tools_tests/package.json +++ b/tests/tools_tests/package.json @@ -2,7 +2,7 @@ "name": "@tests/tools", "private": true, "scripts": { - "build": "rescript legacy build", + "build": "rescript legacy build -warn-error -3", "clean": "rescript clean", "dev": "rescript -w" }, diff --git a/tests/tools_tests/src/expected/DeprecatedStuff.res.expected b/tests/tools_tests/src/expected/DeprecatedStuff.res.expected new file mode 100644 index 0000000000..3a9e14c4f2 --- /dev/null +++ b/tests/tools_tests/src/expected/DeprecatedStuff.res.expected @@ -0,0 +1,12 @@ +@send +external slice: (string, ~from: int, ~to_: int) => string = "slice" + +@send +external shift: array<'a> => option<'a> = "shift" + +module Constants = { + let otherThing = [2, 3] +} + +let deprecatedThing = [1, 2] + diff --git a/tests/tools_tests/src/expected/DeprecatedStuff.resi.expected b/tests/tools_tests/src/expected/DeprecatedStuff.resi.expected new file mode 100644 index 0000000000..df7f2f270f --- /dev/null +++ b/tests/tools_tests/src/expected/DeprecatedStuff.resi.expected @@ -0,0 +1,27 @@ +@deprecated({ + reason: "Use `String.slice` instead", + migrate: String.slice( + ~start=%insert.labelledArgument("from"), + ~end=%insert.labelledArgument("to_"), + ), +}) +@send +external slice: (string, ~from: int, ~to_: int) => string = "slice" + +@send +@deprecated({ + reason: "Use `Array.shift` instead.", + migrate: Array.shift(), +}) +external shift: array<'a> => option<'a> = "shift" + +module Constants: { + let otherThing: array +} + +@deprecated({ + reason: "Use `otherThing` instead.", + migrate: DeprecatedStuff.Constants.otherThing, +}) +let deprecatedThing: array + diff --git a/tests/tools_tests/src/expected/FileToMigrate.res.expected b/tests/tools_tests/src/expected/FileToMigrate.res.expected new file mode 100644 index 0000000000..2572499f87 --- /dev/null +++ b/tests/tools_tests/src/expected/FileToMigrate.res.expected @@ -0,0 +1,11 @@ +let someNiceString = String.slice("abcdefg", ~start=2, ~end=5) + +let someNiceString2 = String.slice(String.slice("abcdefg", ~start=0, ~end=1), ~start=2, ~end=5) + +let someNiceString3 = "abcdefg"->String.slice(~start=2, ~end=5) + +let shift1 = Array.shift([1, 2, 3]) +let shift2 = [1, 2, 3]->Array.shift + +let deprecatedThing1 = DeprecatedStuff.Constants.otherThing + diff --git a/tests/tools_tests/src/expected/StdlibMigrationNoCompile_Array.res.expected b/tests/tools_tests/src/expected/StdlibMigrationNoCompile_Array.res.expected new file mode 100644 index 0000000000..009a006db0 --- /dev/null +++ b/tests/tools_tests/src/expected/StdlibMigrationNoCompile_Array.res.expected @@ -0,0 +1,4 @@ +// Migrations that will not compile after migration (by design) +let sortInPlaceWith1 = [3, 1, 2]->Array.sort((a, b) => a - b) +let sortInPlaceWith2 = Array.sort([3, 1, 2], (a, b) => a - b) + diff --git a/tests/tools_tests/src/expected/StdlibMigrationNoCompile_String.res.expected b/tests/tools_tests/src/expected/StdlibMigrationNoCompile_String.res.expected new file mode 100644 index 0000000000..c99e65e613 --- /dev/null +++ b/tests/tools_tests/src/expected/StdlibMigrationNoCompile_String.res.expected @@ -0,0 +1,12 @@ +let normalizeByForm1 = "abcde"->String.normalizeByForm("a") +let normalizeByForm2 = String.normalizeByForm("abcde", "a") + +let unsafeReplaceBy01 = "abcde"->String.replaceRegExpBy0Unsafe(/d/, (_, _, _) => "f") +let unsafeReplaceBy02 = String.replaceRegExpBy0Unsafe("abcde", /d/, (_, _, _) => "f") + +let unsafeReplaceBy11 = "abcde"->String.replaceRegExpBy1Unsafe(/d/, (_, _, _, _) => "f") +let unsafeReplaceBy12 = String.replaceRegExpBy1Unsafe("abcde", /d/, (_, _, _, _) => "f") + +let unsafeReplaceBy21 = "abcde"->String.replaceRegExpBy2Unsafe(/d/, (_, _, _, _, _) => "f") +let unsafeReplaceBy22 = String.replaceRegExpBy2Unsafe("abcde", /d/, (_, _, _, _, _) => "f") + diff --git a/tests/tools_tests/src/expected/StdlibMigration_Array.res.expected b/tests/tools_tests/src/expected/StdlibMigration_Array.res.expected new file mode 100644 index 0000000000..4f18613d4e --- /dev/null +++ b/tests/tools_tests/src/expected/StdlibMigration_Array.res.expected @@ -0,0 +1,169 @@ +let shift1 = [1, 2, 3]->Array.shift +let shift2 = Array.shift([1, 2, 3]) + +let slice1 = [1, 2, 3]->Array.slice(~start=1, ~end=2) +let slice2 = Array.slice([1, 2, 3], ~start=1, ~end=2) + +external someArrayLike: Js_array2.array_like = "whatever" + +let from1 = someArrayLike->Array.fromArrayLike +let from2 = Array.fromArrayLike(someArrayLike) + +let fromMap1 = someArrayLike->Array.fromArrayLikeWithMap(s => s ++ "!") +let fromMap2 = Array.fromArrayLikeWithMap(someArrayLike, s => s ++ "!") + +let isArray1 = [1, 2, 3]->Array.isArray +let isArray2 = Array.isArray([1, 2, 3]) + +let length1 = [1, 2, 3]->Array.length +let length2 = Array.length([1, 2, 3]) + +let fillInPlace1 = [1, 2, 3]->Array.fillAll(0) +let fillInPlace2 = Array.fillAll([1, 2, 3], 0) + +let fillFromInPlace1 = [1, 2, 3, 4]->Array.fillToEnd(0, ~start=2) +let fillFromInPlace2 = Array.fillToEnd([1, 2, 3, 4], 0, ~start=2) + +let fillRangeInPlace1 = [1, 2, 3, 4]->Array.fill(0, ~start=1, ~end=3) +let fillRangeInPlace2 = Array.fill([1, 2, 3, 4], 0, ~start=1, ~end=3) + +let pop1 = [1, 2, 3]->Array.pop +let pop2 = Array.pop([1, 2, 3]) + +let reverseInPlace1 = [1, 2, 3]->Array.reverse +let reverseInPlace2 = Array.reverse([1, 2, 3]) + +let concat1 = [1, 2]->Array.concat([3, 4]) +let concat2 = Array.concat([1, 2], [3, 4]) + +let concatMany1 = [1, 2]->Array.concatMany([[3, 4], [5, 6]]) +let concatMany2 = Array.concatMany([1, 2], [[3, 4], [5, 6]]) + +let includes1 = [1, 2, 3]->Array.includes(2) +let includes2 = Array.includes([1, 2, 3], 2) + +let indexOf1 = [1, 2, 3]->Array.indexOf(2) +let indexOf2 = Array.indexOf([1, 2, 3], 2) + +let indexOfFrom1 = [1, 2, 1, 3]->Array.indexOfFrom(1, 2) +let indexOfFrom2 = Array.indexOfFrom([1, 2, 1, 3], 1, 2) + +let joinWith1 = [1, 2, 3]->Array.joinUnsafe(",") +let joinWith2 = Array.joinUnsafe([1, 2, 3], ",") + +let lastIndexOf1 = [1, 2, 1, 3]->Array.lastIndexOf(1) +let lastIndexOf2 = Array.lastIndexOf([1, 2, 1, 3], 1) + +let lastIndexOfFrom1 = [1, 2, 1, 3, 1]->Array.lastIndexOfFrom(1, 3) +let lastIndexOfFrom2 = Array.lastIndexOfFrom([1, 2, 1, 3, 1], 1, 3) + +let copy1 = [1, 2, 3]->Array.copy +let copy2 = Array.copy([1, 2, 3]) + +let sliceFrom1 = [1, 2, 3, 4]->Array.sliceToEnd(~start=2) +let sliceFrom2 = Array.sliceToEnd([1, 2, 3, 4], ~start=2) + +let toString1 = [1, 2, 3]->Array.toString +let toString2 = Array.toString([1, 2, 3]) + +let toLocaleString1 = [1, 2, 3]->Array.toLocaleString +let toLocaleString2 = Array.toLocaleString([1, 2, 3]) + +let every1 = [2, 4, 6]->Array.every(x => mod(x, 2) == 0) +let every2 = Array.every([2, 4, 6], x => mod(x, 2) == 0) + +let everyi1 = [0, 1, 2]->Array.everyWithIndex((x, i) => x == i) +let everyi2 = Array.everyWithIndex([0, 1, 2], (x, i) => x == i) + +let filter1 = [1, 2, 3, 4]->Array.filter(x => x > 2) +let filter2 = Array.filter([1, 2, 3, 4], x => x > 2) + +let filteri1 = [0, 1, 2, 3]->Array.filterWithIndex((_x, i) => i > 1) +let filteri2 = Array.filterWithIndex([0, 1, 2, 3], (_x, i) => i > 1) + +let find1 = [1, 2, 3, 4]->Array.find(x => x > 2) +let find2 = Array.find([1, 2, 3, 4], x => x > 2) + +let findi1 = [0, 1, 2, 3]->Array.findWithIndex((_x, i) => i > 1) +let findi2 = Array.findWithIndex([0, 1, 2, 3], (_x, i) => i > 1) + +let findIndex1 = [1, 2, 3, 4]->Array.findIndex(x => x > 2) +let findIndex2 = Array.findIndex([1, 2, 3, 4], x => x > 2) + +let findIndexi1 = [0, 1, 2, 3]->Array.findIndexWithIndex((_x, i) => i > 1) +let findIndexi2 = Array.findIndexWithIndex([0, 1, 2, 3], (_x, i) => i > 1) + +let forEach1 = [1, 2, 3]->Array.forEach(x => ignore(x)) +let forEach2 = Array.forEach([1, 2, 3], x => ignore(x)) + +let forEachi1 = [1, 2, 3]->Array.forEachWithIndex((x, i) => ignore(x + i)) +let forEachi2 = Array.forEachWithIndex([1, 2, 3], (x, i) => ignore(x + i)) + +let map1 = [1, 2, 3]->Array.map(x => x * 2) +let map2 = Array.map([1, 2, 3], x => x * 2) + +let mapi1 = [1, 2, 3]->Array.mapWithIndex((x, i) => x + i) +let mapi2 = Array.mapWithIndex([1, 2, 3], (x, i) => x + i) + +let some1 = [1, 2, 3, 4]->Array.some(x => x > 3) +let some2 = Array.some([1, 2, 3, 4], x => x > 3) + +let somei1 = [0, 1, 2, 3]->Array.someWithIndex((_x, i) => i > 2) +let somei2 = Array.someWithIndex([0, 1, 2, 3], (_x, i) => i > 2) + +let unsafeGet1 = [1, 2, 3]->Array.getUnsafe(1) +let unsafeGet2 = Array.getUnsafe([1, 2, 3], 1) + +let unsafeSet1 = [1, 2, 3]->Array.setUnsafe(1, 5) +let unsafeSet2 = Array.setUnsafe([1, 2, 3], 1, 5) + +let copyWithin1 = [1, 2, 3, 4, 5]->Array.copyAllWithin(~target=2) +let copyWithin2 = Array.copyAllWithin([1, 2, 3, 4, 5], ~target=2) + +let copyWithinFrom1 = [1, 2, 3, 4, 5]->Array.copyWithinToEnd(~target=0, ~start=2) +let copyWithinFrom2 = Array.copyWithinToEnd([1, 2, 3, 4, 5], ~target=0, ~start=2) + +let copyWithinFromRange1 = [1, 2, 3, 4, 5, 6]->Array.copyWithin(~target=1, ~start=2, ~end=5) +let copyWithinFromRange2 = Array.copyWithin([1, 2, 3, 4, 5, 6], ~target=1, ~start=2, ~end=5) + +let push1 = [1, 2, 3]->Array.push(4) +let push2 = Array.push([1, 2, 3], 4) + +let pushMany1 = [1, 2, 3]->Array.pushMany([4, 5]) +let pushMany2 = Array.pushMany([1, 2, 3], [4, 5]) + +let sortInPlace1 = + ["c", "a", "b"]->Array.toSorted((a, b) => + %todo("This needs a comparator function. Use `String.compare` for strings, etc.") + ) +let sortInPlace2 = Array.toSorted(["c", "a", "b"], (a, b) => + %todo("This needs a comparator function. Use `String.compare` for strings, etc.") +) + +let unshift1 = [1, 2, 3]->Array.unshift(4) +let unshift2 = Array.unshift([1, 2, 3], 4) + +let unshiftMany1 = [1, 2, 3]->Array.unshiftMany([4, 5]) +let unshiftMany2 = Array.unshiftMany([1, 2, 3], [4, 5]) + +let reduce1 = [1, 2, 3]->Array.reduce(0, (acc, x) => acc + x) +let reduce2 = Array.reduce([1, 2, 3], 0, (acc, x) => acc + x) + +let spliceInPlace1 = [1, 2, 3]->Array.splice(~start=1, ~remove=1, ~insert=[4, 5]) +let spliceInPlace2 = Array.splice([1, 2, 3], ~start=1, ~remove=1, ~insert=[4, 5]) + +let removeFromInPlace1 = [1, 2, 3]->Array.removeInPlace(1) +let removeFromInPlace2 = Array.removeInPlace([1, 2, 3], 1) + +let removeCountInPlace1 = [1, 2, 3]->Array.splice(~start=1, ~remove=1, ~insert=[]) +let removeCountInPlace2 = Array.splice([1, 2, 3], ~start=1, ~remove=1, ~insert=[]) + +let reducei1 = [1, 2, 3]->Array.reduceWithIndex(0, (acc, x, i) => acc + x + i) +let reducei2 = Array.reduceWithIndex([1, 2, 3], 0, (acc, x, i) => acc + x + i) + +let reduceRight1 = [1, 2, 3]->Array.reduceRight(0, (acc, x) => acc + x) +let reduceRight2 = Array.reduceRight([1, 2, 3], 0, (acc, x) => acc + x) + +let reduceRighti1 = [1, 2, 3]->Array.reduceRightWithIndex(0, (acc, x, i) => acc + x + i) +let reduceRighti2 = Array.reduceRightWithIndex([1, 2, 3], 0, (acc, x, i) => acc + x + i) + diff --git a/tests/tools_tests/src/expected/StdlibMigration_BigInt.res.expected b/tests/tools_tests/src/expected/StdlibMigration_BigInt.res.expected new file mode 100644 index 0000000000..e674d8aee7 --- /dev/null +++ b/tests/tools_tests/src/expected/StdlibMigration_BigInt.res.expected @@ -0,0 +1,48 @@ +let fromStringExn1 = "123"->BigInt.fromStringOrThrow +let fromStringExn2 = BigInt.fromStringOrThrow("123") + +let land1 = 7n->BigInt.bitwiseAnd(4n) +let land2 = 7n & 4n + +let lor1 = 7n->BigInt.bitwiseOr(4n) +let lor2 = BigInt.bitwiseOr(7n, 4n) + +let lxor1 = 7n->BigInt.bitwiseXor(4n) +let lxor2 = 7n ^ 4n + +let lnot1 = 2n->Js.BigInt.lnot +let lnot2 = Js.BigInt.lnot(2n) + +let lsl1 = 4n->BigInt.shiftLeft(1n) +let lsl2 = 4n << 1n + +let asr1 = 8n->BigInt.shiftRight(1n) +let asr2 = 8n >> 1n + +let toString1 = 123n->BigInt.toString +let toString2 = BigInt.toString(123n) + +let toLocaleString1 = 123n->BigInt.toLocaleString +let toLocaleString2 = BigInt.toLocaleString(123n) + +// From the stdlib module +let stdlib_fromStringExn1 = "123"->BigInt.fromStringOrThrow +let stdlib_fromStringExn2 = BigInt.fromStringOrThrow("123") + +let stdlib_land1 = 7n->BigInt.bitwiseAnd(4n) +let stdlib_land2 = 7n & 4n + +let stdlib_lor1 = BigInt.bitwiseOr(7n, 4n) + +let stdlib_lxor1 = 7n->BigInt.bitwiseXor(4n) +let stdlib_lxor2 = 7n ^ 4n + +let stdlib_lnot1 = 2n->BigInt.bitwiseNot +let stdlib_lnot2 = ~2n + +let stdlib_lsl1 = 4n->BigInt.shiftLeft(1n) +let stdlib_lsl2 = 4n << 1n + +let stdlib_asr1 = 8n->BigInt.shiftRight(1n) +let stdlib_asr2 = 8n >> 1n + diff --git a/tests/tools_tests/src/expected/StdlibMigration_Console.res.expected b/tests/tools_tests/src/expected/StdlibMigration_Console.res.expected new file mode 100644 index 0000000000..472198684f --- /dev/null +++ b/tests/tools_tests/src/expected/StdlibMigration_Console.res.expected @@ -0,0 +1,29 @@ +let log = Console.log("Hello, World!") +let log2 = Console.log2("Hello", "World") +let log3 = Console.log3("Hello", "World", "!") +let log4 = Console.log4("Hello", "World", "!", "!") +let logMany = Console.logMany(["Hello", "World"]) + +let info = Console.info("Hello, World!") +let info2 = Console.info2("Hello", "World") +let info3 = Console.info3("Hello", "World", "!") +let info4 = Console.info4("Hello", "World", "!", "!") +let infoMany = Console.infoMany(["Hello", "World"]) + +let warn = Console.warn("Hello, World!") +let warn2 = Console.warn2("Hello", "World") +let warn3 = Console.warn3("Hello", "World", "!") +let warn4 = Console.warn4("Hello", "World", "!", "!") +let warnMany = Console.warnMany(["Hello", "World"]) + +let error = Console.error("Hello, World!") +let error2 = Console.error2("Hello", "World") +let error3 = Console.error3("Hello", "World", "!") +let error4 = Console.error4("Hello", "World", "!", "!") +let errorMany = Console.errorMany(["Hello", "World"]) + +let trace = Console.trace() +let timeStart = Console.time("Hello, World!") +let timeEnd = Console.timeEnd("Hello, World!") +let table = Console.table(["Hello", "World"]) + diff --git a/tests/tools_tests/src/expected/StdlibMigration_Int.res.expected b/tests/tools_tests/src/expected/StdlibMigration_Int.res.expected new file mode 100644 index 0000000000..49289fa30b --- /dev/null +++ b/tests/tools_tests/src/expected/StdlibMigration_Int.res.expected @@ -0,0 +1,8 @@ +let result1 = Int.bitwiseAnd(1, 2) +let result2 = Int.bitwiseOr(1, 2) +let result3 = Int.bitwiseXor(1, 2) +let result4 = Int.shiftLeft(1, 2) +let result5 = Int.shiftRightUnsigned(1, 2) +let result6 = Int.shiftRight(1, 2) +let result7 = Int.bitwiseNot(0) + diff --git a/tests/tools_tests/src/expected/StdlibMigration_JSON.res.expected b/tests/tools_tests/src/expected/StdlibMigration_JSON.res.expected new file mode 100644 index 0000000000..f5e4af5f9c --- /dev/null +++ b/tests/tools_tests/src/expected/StdlibMigration_JSON.res.expected @@ -0,0 +1,19 @@ +external someJson: Js_json.t = "someJson" +external strToJson: string => Js_json.t = "strToJson" + +let decodeString1 = switch someJson { +| JSON.String(str) => Some(str) +| _ => None +} +let decodeString2 = switch someJson { +| JSON.String(str) => Some(str) +| _ => None +} +let decodeString3 = switch [1, 2, 3] +->Array.map(v => v->Int.toString) +->Array.join(" ") +->strToJson { +| JSON.String(str) => Some(str) +| _ => None +} + diff --git a/tests/tools_tests/src/expected/StdlibMigration_Js.res.expected b/tests/tools_tests/src/expected/StdlibMigration_Js.res.expected new file mode 100644 index 0000000000..e87cdd9b25 --- /dev/null +++ b/tests/tools_tests/src/expected/StdlibMigration_Js.res.expected @@ -0,0 +1,6 @@ +let consoleLog1 = Console.log("Hello") +let consoleLog2 = Console.log2("Hello", "World") +let consoleLog3 = Console.log3("Hello", "World", "!") +let consoleLog4 = Console.log4("Hello", "World", "!", "!") +let consoleLogMany = Console.logMany(["Hello", "World"]) + diff --git a/tests/tools_tests/src/expected/StdlibMigration_String.res.expected b/tests/tools_tests/src/expected/StdlibMigration_String.res.expected new file mode 100644 index 0000000000..031edd3828 --- /dev/null +++ b/tests/tools_tests/src/expected/StdlibMigration_String.res.expected @@ -0,0 +1,126 @@ +let make1 = 1->String.make +let make2 = String.make(1) + +let fromCharCode1 = 65->String.fromCharCode +let fromCharCode2 = String.fromCharCode(65) + +let fromCharCodeMany1 = [65, 66, 67]->String.fromCharCodeMany +let fromCharCodeMany2 = String.fromCharCodeMany([65, 66, 67]) + +let fromCodePoint1 = 65->String.fromCodePoint +let fromCodePoint2 = String.fromCodePoint(65) + +let fromCodePointMany1 = [65, 66, 67]->String.fromCodePointMany +let fromCodePointMany2 = String.fromCodePointMany([65, 66, 67]) + +let length1 = "abcde"->String.length +let length2 = String.length("abcde") + +let get1 = "abcde"->String.getUnsafe(2) +let get2 = String.getUnsafe("abcde", 2) + +let charAt1 = "abcde"->String.charAt(2) +let charAt2 = String.charAt("abcde", 2) + +let charCodeAt1 = "abcde"->String.charCodeAt(2) +let charCodeAt2 = String.charCodeAt("abcde", 2) + +let codePointAt1 = "abcde"->String.codePointAt(2) +let codePointAt2 = String.codePointAt("abcde", 2) + +let concat1 = "abcde"->String.concat("fghij") +let concat2 = String.concat("abcde", "fghij") + +let concatMany1 = "abcde"->String.concatMany(["fghij", "klmno"]) +let concatMany2 = String.concatMany("abcde", ["fghij", "klmno"]) + +let endsWith1 = "abcde"->String.endsWith("de") +let endsWith2 = String.endsWith("abcde", "de") + +let endsWithFrom1 = "abcde"->String.endsWithFrom("d", 2) +let endsWithFrom2 = String.endsWithFrom("abcde", "d", 2) + +let includes1 = "abcde"->String.includes("de") +let includes2 = String.includes("abcde", "de") + +let includesFrom1 = "abcde"->String.includesFrom("d", 2) +let includesFrom2 = String.includesFrom("abcde", "d", 2) + +let indexOf1 = "abcde"->String.indexOf("de") +let indexOf2 = String.indexOf("abcde", "de") + +let indexOfFrom1 = "abcde"->String.indexOfFrom("d", 2) +let indexOfFrom2 = String.indexOfFrom("abcde", "d", 2) + +let lastIndexOf1 = "abcde"->String.lastIndexOf("de") +let lastIndexOf2 = String.lastIndexOf("abcde", "de") + +let lastIndexOfFrom1 = "abcde"->String.lastIndexOfFrom("d", 2) +let lastIndexOfFrom2 = String.lastIndexOfFrom("abcde", "d", 2) + +let localeCompare1 = "abcde"->String.localeCompare("fghij") +let localeCompare2 = String.localeCompare("abcde", "fghij") + +let match1 = "abcde"->String.match(/d/) +let match2 = String.match("abcde", /d/) + +let normalize1 = "abcde"->String.normalize +let normalize2 = String.normalize("abcde") + +let repeat1 = "abcde"->String.repeat(2) +let repeat2 = String.repeat("abcde", 2) + +let replace1 = "abcde"->String.replace("d", "f") +let replace2 = String.replace("abcde", "d", "f") + +let replaceByRe1 = "abcde"->String.replaceRegExp(/d/, "f") +let replaceByRe2 = String.replaceRegExp("abcde", /d/, "f") + +let search1 = "abcde"->String.search(/d/) +let search2 = String.search("abcde", /d/) + +let slice1 = "abcde"->String.slice(~start=1, ~end=3) +let slice2 = String.slice("abcde", ~start=1, ~end=3) + +let sliceToEnd1 = "abcde"->String.sliceToEnd(~start=1) +let sliceToEnd2 = String.sliceToEnd("abcde", ~start=1) + +let split1 = "abcde"->String.split("d") +let split2 = String.split("abcde", "d") + +let splitAtMost1 = "abcde"->String.splitAtMost("d", ~limit=2) +let splitAtMost2 = String.splitAtMost("abcde", "d", ~limit=2) + +let splitByRe1 = "abcde"->String.splitByRegExp(/d/) +let splitByRe2 = String.splitByRegExp("abcde", /d/) + +let splitByReAtMost1 = "abcde"->String.splitByRegExpAtMost(/d/, ~limit=2) +let splitByReAtMost2 = String.splitByRegExpAtMost("abcde", /d/, ~limit=2) + +let startsWith1 = "abcde"->String.startsWith("ab") +let startsWith2 = String.startsWith("abcde", "ab") + +let startsWithFrom1 = "abcde"->String.startsWithFrom("b", 1) +let startsWithFrom2 = String.startsWithFrom("abcde", "b", 1) + +let substring1 = "abcde"->String.substring(~start=1, ~end=3) +let substring2 = String.substring("abcde", ~start=1, ~end=3) + +let substringToEnd1 = "abcde"->String.substringToEnd(~start=1) +let substringToEnd2 = String.substringToEnd("abcde", ~start=1) + +let toLowerCase1 = "abcde"->String.toLowerCase +let toLowerCase2 = String.toLowerCase("abcde") + +let toLocaleLowerCase1 = "abcde"->String.toLocaleLowerCase +let toLocaleLowerCase2 = String.toLocaleLowerCase("abcde") + +let toUpperCase1 = "abcde"->String.toUpperCase +let toUpperCase2 = String.toUpperCase("abcde") + +let toLocaleUpperCase1 = "abcde"->String.toLocaleUpperCase +let toLocaleUpperCase2 = String.toLocaleUpperCase("abcde") + +let trim1 = "abcde"->String.trim +let trim2 = String.trim("abcde") + diff --git a/tests/tools_tests/src/migrate/DeprecatedStuff.res b/tests/tools_tests/src/migrate/DeprecatedStuff.res new file mode 100644 index 0000000000..ec1494961e --- /dev/null +++ b/tests/tools_tests/src/migrate/DeprecatedStuff.res @@ -0,0 +1,11 @@ +@send +external slice: (string, ~from: int, ~to_: int) => string = "slice" + +@send +external shift: array<'a> => option<'a> = "shift" + +module Constants = { + let otherThing = [2, 3] +} + +let deprecatedThing = [1, 2] diff --git a/tests/tools_tests/src/migrate/DeprecatedStuff.resi b/tests/tools_tests/src/migrate/DeprecatedStuff.resi new file mode 100644 index 0000000000..1c91c3e439 --- /dev/null +++ b/tests/tools_tests/src/migrate/DeprecatedStuff.resi @@ -0,0 +1,26 @@ +@deprecated({ + reason: "Use `String.slice` instead", + migrate: String.slice( + ~start=%insert.labelledArgument("from"), + ~end=%insert.labelledArgument("to_"), + ), +}) +@send +external slice: (string, ~from: int, ~to_: int) => string = "slice" + +@send +@deprecated({ + reason: "Use `Array.shift` instead.", + migrate: Array.shift(), +}) +external shift: array<'a> => option<'a> = "shift" + +module Constants: { + let otherThing: array +} + +@deprecated({ + reason: "Use `otherThing` instead.", + migrate: DeprecatedStuff.Constants.otherThing, +}) +let deprecatedThing: array diff --git a/tests/tools_tests/src/migrate/FileToMigrate.res b/tests/tools_tests/src/migrate/FileToMigrate.res new file mode 100644 index 0000000000..097d2f5c21 --- /dev/null +++ b/tests/tools_tests/src/migrate/FileToMigrate.res @@ -0,0 +1,14 @@ +let someNiceString = DeprecatedStuff.slice("abcdefg", ~from=2, ~to_=5) + +let someNiceString2 = DeprecatedStuff.slice( + DeprecatedStuff.slice("abcdefg", ~from=0, ~to_=1), + ~from=2, + ~to_=5, +) + +let someNiceString3 = "abcdefg"->DeprecatedStuff.slice(~from=2, ~to_=5) + +let shift1 = DeprecatedStuff.shift([1, 2, 3]) +let shift2 = [1, 2, 3]->DeprecatedStuff.shift + +let deprecatedThing1 = DeprecatedStuff.deprecatedThing diff --git a/tests/tools_tests/src/migrate/StdlibMigrationNoCompile_Array.res b/tests/tools_tests/src/migrate/StdlibMigrationNoCompile_Array.res new file mode 100644 index 0000000000..369db964f3 --- /dev/null +++ b/tests/tools_tests/src/migrate/StdlibMigrationNoCompile_Array.res @@ -0,0 +1,3 @@ +// Migrations that will not compile after migration (by design) +let sortInPlaceWith1 = [3, 1, 2]->Js.Array2.sortInPlaceWith((a, b) => a - b) +let sortInPlaceWith2 = Js.Array2.sortInPlaceWith([3, 1, 2], (a, b) => a - b) diff --git a/tests/tools_tests/src/migrate/StdlibMigrationNoCompile_String.res b/tests/tools_tests/src/migrate/StdlibMigrationNoCompile_String.res new file mode 100644 index 0000000000..d377bf2d05 --- /dev/null +++ b/tests/tools_tests/src/migrate/StdlibMigrationNoCompile_String.res @@ -0,0 +1,11 @@ +let normalizeByForm1 = "abcde"->Js.String2.normalizeByForm("a") +let normalizeByForm2 = Js.String2.normalizeByForm("abcde", "a") + +let unsafeReplaceBy01 = "abcde"->Js.String2.unsafeReplaceBy0(/d/, (_, _, _) => "f") +let unsafeReplaceBy02 = Js.String2.unsafeReplaceBy0("abcde", /d/, (_, _, _) => "f") + +let unsafeReplaceBy11 = "abcde"->Js.String2.unsafeReplaceBy1(/d/, (_, _, _, _) => "f") +let unsafeReplaceBy12 = Js.String2.unsafeReplaceBy1("abcde", /d/, (_, _, _, _) => "f") + +let unsafeReplaceBy21 = "abcde"->Js.String2.unsafeReplaceBy2(/d/, (_, _, _, _, _) => "f") +let unsafeReplaceBy22 = Js.String2.unsafeReplaceBy2("abcde", /d/, (_, _, _, _, _) => "f") diff --git a/tests/tools_tests/src/migrate/StdlibMigration_Array.res b/tests/tools_tests/src/migrate/StdlibMigration_Array.res new file mode 100644 index 0000000000..cf8e65a744 --- /dev/null +++ b/tests/tools_tests/src/migrate/StdlibMigration_Array.res @@ -0,0 +1,169 @@ +let shift1 = [1, 2, 3]->Js.Array2.shift +let shift2 = Js.Array2.shift([1, 2, 3]) + +let slice1 = [1, 2, 3]->Js.Array2.slice(~start=1, ~end_=2) +let slice2 = Js.Array2.slice([1, 2, 3], ~start=1, ~end_=2) + +external someArrayLike: Js_array2.array_like = "whatever" + +let from1 = someArrayLike->Js.Array2.from +let from2 = Js.Array2.from(someArrayLike) + +let fromMap1 = someArrayLike->Js.Array2.fromMap(s => s ++ "!") +let fromMap2 = Js.Array2.fromMap(someArrayLike, s => s ++ "!") + +let isArray1 = [1, 2, 3]->Js.Array2.isArray +let isArray2 = Js.Array2.isArray([1, 2, 3]) + +let length1 = [1, 2, 3]->Js.Array2.length +let length2 = Js.Array2.length([1, 2, 3]) + +let fillInPlace1 = [1, 2, 3]->Js.Array2.fillInPlace(0) +let fillInPlace2 = Js.Array2.fillInPlace([1, 2, 3], 0) + +let fillFromInPlace1 = [1, 2, 3, 4]->Js.Array2.fillFromInPlace(0, ~from=2) +let fillFromInPlace2 = Js.Array2.fillFromInPlace([1, 2, 3, 4], 0, ~from=2) + +let fillRangeInPlace1 = [1, 2, 3, 4]->Js.Array2.fillRangeInPlace(0, ~start=1, ~end_=3) +let fillRangeInPlace2 = Js.Array2.fillRangeInPlace([1, 2, 3, 4], 0, ~start=1, ~end_=3) + +let pop1 = [1, 2, 3]->Js.Array2.pop +let pop2 = Js.Array2.pop([1, 2, 3]) + +let reverseInPlace1 = [1, 2, 3]->Js.Array2.reverseInPlace +let reverseInPlace2 = Js.Array2.reverseInPlace([1, 2, 3]) + +let concat1 = [1, 2]->Js.Array2.concat([3, 4]) +let concat2 = Js.Array2.concat([1, 2], [3, 4]) + +let concatMany1 = [1, 2]->Js.Array2.concatMany([[3, 4], [5, 6]]) +let concatMany2 = Js.Array2.concatMany([1, 2], [[3, 4], [5, 6]]) + +let includes1 = [1, 2, 3]->Js.Array2.includes(2) +let includes2 = Js.Array2.includes([1, 2, 3], 2) + +let indexOf1 = [1, 2, 3]->Js.Array2.indexOf(2) +let indexOf2 = Js.Array2.indexOf([1, 2, 3], 2) + +let indexOfFrom1 = [1, 2, 1, 3]->Js.Array2.indexOfFrom(1, ~from=2) +let indexOfFrom2 = Js.Array2.indexOfFrom([1, 2, 1, 3], 1, ~from=2) + +let joinWith1 = [1, 2, 3]->Js.Array2.joinWith(",") +let joinWith2 = Js.Array2.joinWith([1, 2, 3], ",") + +let lastIndexOf1 = [1, 2, 1, 3]->Js.Array2.lastIndexOf(1) +let lastIndexOf2 = Js.Array2.lastIndexOf([1, 2, 1, 3], 1) + +let lastIndexOfFrom1 = [1, 2, 1, 3, 1]->Js.Array2.lastIndexOfFrom(1, ~from=3) +let lastIndexOfFrom2 = Js.Array2.lastIndexOfFrom([1, 2, 1, 3, 1], 1, ~from=3) + +let copy1 = [1, 2, 3]->Js.Array2.copy +let copy2 = Js.Array2.copy([1, 2, 3]) + +let sliceFrom1 = [1, 2, 3, 4]->Js.Array2.sliceFrom(2) +let sliceFrom2 = Js.Array2.sliceFrom([1, 2, 3, 4], 2) + +let toString1 = [1, 2, 3]->Js.Array2.toString +let toString2 = Js.Array2.toString([1, 2, 3]) + +let toLocaleString1 = [1, 2, 3]->Js.Array2.toLocaleString +let toLocaleString2 = Js.Array2.toLocaleString([1, 2, 3]) + +let every1 = [2, 4, 6]->Js.Array2.every(x => mod(x, 2) == 0) +let every2 = Js.Array2.every([2, 4, 6], x => mod(x, 2) == 0) + +let everyi1 = [0, 1, 2]->Js.Array2.everyi((x, i) => x == i) +let everyi2 = Js.Array2.everyi([0, 1, 2], (x, i) => x == i) + +let filter1 = [1, 2, 3, 4]->Js.Array2.filter(x => x > 2) +let filter2 = Js.Array2.filter([1, 2, 3, 4], x => x > 2) + +let filteri1 = [0, 1, 2, 3]->Js.Array2.filteri((_x, i) => i > 1) +let filteri2 = Js.Array2.filteri([0, 1, 2, 3], (_x, i) => i > 1) + +let find1 = [1, 2, 3, 4]->Js.Array2.find(x => x > 2) +let find2 = Js.Array2.find([1, 2, 3, 4], x => x > 2) + +let findi1 = [0, 1, 2, 3]->Js.Array2.findi((_x, i) => i > 1) +let findi2 = Js.Array2.findi([0, 1, 2, 3], (_x, i) => i > 1) + +let findIndex1 = [1, 2, 3, 4]->Js.Array2.findIndex(x => x > 2) +let findIndex2 = Js.Array2.findIndex([1, 2, 3, 4], x => x > 2) + +let findIndexi1 = [0, 1, 2, 3]->Js.Array2.findIndexi((_x, i) => i > 1) +let findIndexi2 = Js.Array2.findIndexi([0, 1, 2, 3], (_x, i) => i > 1) + +let forEach1 = [1, 2, 3]->Js.Array2.forEach(x => ignore(x)) +let forEach2 = Js.Array2.forEach([1, 2, 3], x => ignore(x)) + +let forEachi1 = [1, 2, 3]->Js.Array2.forEachi((x, i) => ignore(x + i)) +let forEachi2 = Js.Array2.forEachi([1, 2, 3], (x, i) => ignore(x + i)) + +let map1 = [1, 2, 3]->Js.Array2.map(x => x * 2) +let map2 = Js.Array2.map([1, 2, 3], x => x * 2) + +let mapi1 = [1, 2, 3]->Js.Array2.mapi((x, i) => x + i) +let mapi2 = Js.Array2.mapi([1, 2, 3], (x, i) => x + i) + +let some1 = [1, 2, 3, 4]->Js.Array2.some(x => x > 3) +let some2 = Js.Array2.some([1, 2, 3, 4], x => x > 3) + +let somei1 = [0, 1, 2, 3]->Js.Array2.somei((_x, i) => i > 2) +let somei2 = Js.Array2.somei([0, 1, 2, 3], (_x, i) => i > 2) + +let unsafeGet1 = [1, 2, 3]->Js.Array2.unsafe_get(1) +let unsafeGet2 = Js.Array2.unsafe_get([1, 2, 3], 1) + +let unsafeSet1 = [1, 2, 3]->Js.Array2.unsafe_set(1, 5) +let unsafeSet2 = Js.Array2.unsafe_set([1, 2, 3], 1, 5) + +let copyWithin1 = [1, 2, 3, 4, 5]->Js.Array2.copyWithin(~to_=2) +let copyWithin2 = Js.Array2.copyWithin([1, 2, 3, 4, 5], ~to_=2) + +let copyWithinFrom1 = [1, 2, 3, 4, 5]->Js.Array2.copyWithinFrom(~to_=0, ~from=2) +let copyWithinFrom2 = Js.Array2.copyWithinFrom([1, 2, 3, 4, 5], ~to_=0, ~from=2) + +let copyWithinFromRange1 = + [1, 2, 3, 4, 5, 6]->Js.Array2.copyWithinFromRange(~to_=1, ~start=2, ~end_=5) +let copyWithinFromRange2 = Js.Array2.copyWithinFromRange( + [1, 2, 3, 4, 5, 6], + ~to_=1, + ~start=2, + ~end_=5, +) + +let push1 = [1, 2, 3]->Js.Array2.push(4) +let push2 = Js.Array2.push([1, 2, 3], 4) + +let pushMany1 = [1, 2, 3]->Js.Array2.pushMany([4, 5]) +let pushMany2 = Js.Array2.pushMany([1, 2, 3], [4, 5]) + +let sortInPlace1 = ["c", "a", "b"]->Js.Array2.sortInPlace +let sortInPlace2 = Js.Array2.sortInPlace(["c", "a", "b"]) + +let unshift1 = [1, 2, 3]->Js.Array2.unshift(4) +let unshift2 = Js.Array2.unshift([1, 2, 3], 4) + +let unshiftMany1 = [1, 2, 3]->Js.Array2.unshiftMany([4, 5]) +let unshiftMany2 = Js.Array2.unshiftMany([1, 2, 3], [4, 5]) + +let reduce1 = [1, 2, 3]->Js.Array2.reduce((acc, x) => acc + x, 0) +let reduce2 = Js.Array2.reduce([1, 2, 3], (acc, x) => acc + x, 0) + +let spliceInPlace1 = [1, 2, 3]->Js.Array2.spliceInPlace(~pos=1, ~remove=1, ~add=[4, 5]) +let spliceInPlace2 = Js.Array2.spliceInPlace([1, 2, 3], ~pos=1, ~remove=1, ~add=[4, 5]) + +let removeFromInPlace1 = [1, 2, 3]->Js.Array2.removeFromInPlace(~pos=1) +let removeFromInPlace2 = Js.Array2.removeFromInPlace([1, 2, 3], ~pos=1) + +let removeCountInPlace1 = [1, 2, 3]->Js.Array2.removeCountInPlace(~pos=1, ~count=1) +let removeCountInPlace2 = Js.Array2.removeCountInPlace([1, 2, 3], ~pos=1, ~count=1) + +let reducei1 = [1, 2, 3]->Js.Array2.reducei((acc, x, i) => acc + x + i, 0) +let reducei2 = Js.Array2.reducei([1, 2, 3], (acc, x, i) => acc + x + i, 0) + +let reduceRight1 = [1, 2, 3]->Js.Array2.reduceRight((acc, x) => acc + x, 0) +let reduceRight2 = Js.Array2.reduceRight([1, 2, 3], (acc, x) => acc + x, 0) + +let reduceRighti1 = [1, 2, 3]->Js.Array2.reduceRighti((acc, x, i) => acc + x + i, 0) +let reduceRighti2 = Js.Array2.reduceRighti([1, 2, 3], (acc, x, i) => acc + x + i, 0) diff --git a/tests/tools_tests/src/migrate/StdlibMigration_BigInt.res b/tests/tools_tests/src/migrate/StdlibMigration_BigInt.res new file mode 100644 index 0000000000..219f3dd56f --- /dev/null +++ b/tests/tools_tests/src/migrate/StdlibMigration_BigInt.res @@ -0,0 +1,47 @@ +let fromStringExn1 = "123"->Js.BigInt.fromStringExn +let fromStringExn2 = Js.BigInt.fromStringExn("123") + +let land1 = 7n->Js.BigInt.land(4n) +let land2 = Js.BigInt.land(7n, 4n) + +let lor1 = 7n->Js.BigInt.lor(4n) +let lor2 = Js.BigInt.lor(7n, 4n) + +let lxor1 = 7n->Js.BigInt.lxor(4n) +let lxor2 = Js.BigInt.lxor(7n, 4n) + +let lnot1 = 2n->Js.BigInt.lnot +let lnot2 = Js.BigInt.lnot(2n) + +let lsl1 = 4n->Js.BigInt.lsl(1n) +let lsl2 = Js.BigInt.lsl(4n, 1n) + +let asr1 = 8n->Js.BigInt.asr(1n) +let asr2 = Js.BigInt.asr(8n, 1n) + +let toString1 = 123n->Js.BigInt.toString +let toString2 = Js.BigInt.toString(123n) + +let toLocaleString1 = 123n->Js.BigInt.toLocaleString +let toLocaleString2 = Js.BigInt.toLocaleString(123n) + +// From the stdlib module +let stdlib_fromStringExn1 = "123"->BigInt.fromStringExn +let stdlib_fromStringExn2 = BigInt.fromStringExn("123") + +let stdlib_land1 = 7n->BigInt.land(4n) +let stdlib_land2 = BigInt.land(7n, 4n) + +let stdlib_lor1 = BigInt.lor(7n, 4n) + +let stdlib_lxor1 = 7n->BigInt.lxor(4n) +let stdlib_lxor2 = BigInt.lxor(7n, 4n) + +let stdlib_lnot1 = 2n->BigInt.lnot +let stdlib_lnot2 = BigInt.lnot(2n) + +let stdlib_lsl1 = 4n->BigInt.lsl(1n) +let stdlib_lsl2 = BigInt.lsl(4n, 1n) + +let stdlib_asr1 = 8n->BigInt.asr(1n) +let stdlib_asr2 = BigInt.asr(8n, 1n) diff --git a/tests/tools_tests/src/migrate/StdlibMigration_Console.res b/tests/tools_tests/src/migrate/StdlibMigration_Console.res new file mode 100644 index 0000000000..0e142a0575 --- /dev/null +++ b/tests/tools_tests/src/migrate/StdlibMigration_Console.res @@ -0,0 +1,28 @@ +let log = Js_console.log("Hello, World!") +let log2 = Js_console.log2("Hello", "World") +let log3 = Js_console.log3("Hello", "World", "!") +let log4 = Js_console.log4("Hello", "World", "!", "!") +let logMany = Js_console.logMany(["Hello", "World"]) + +let info = Js_console.info("Hello, World!") +let info2 = Js_console.info2("Hello", "World") +let info3 = Js_console.info3("Hello", "World", "!") +let info4 = Js_console.info4("Hello", "World", "!", "!") +let infoMany = Js_console.infoMany(["Hello", "World"]) + +let warn = Js_console.warn("Hello, World!") +let warn2 = Js_console.warn2("Hello", "World") +let warn3 = Js_console.warn3("Hello", "World", "!") +let warn4 = Js_console.warn4("Hello", "World", "!", "!") +let warnMany = Js_console.warnMany(["Hello", "World"]) + +let error = Js_console.error("Hello, World!") +let error2 = Js_console.error2("Hello", "World") +let error3 = Js_console.error3("Hello", "World", "!") +let error4 = Js_console.error4("Hello", "World", "!", "!") +let errorMany = Js_console.errorMany(["Hello", "World"]) + +let trace = Js_console.trace() +let timeStart = Js_console.timeStart("Hello, World!") +let timeEnd = Js_console.timeEnd("Hello, World!") +let table = Js_console.table(["Hello", "World"]) diff --git a/tests/tools_tests/src/migrate/StdlibMigration_Int.res b/tests/tools_tests/src/migrate/StdlibMigration_Int.res new file mode 100644 index 0000000000..b76172c1a1 --- /dev/null +++ b/tests/tools_tests/src/migrate/StdlibMigration_Int.res @@ -0,0 +1,7 @@ +let result1 = Int.Bitwise.land(1, 2) +let result2 = Int.Bitwise.lor(1, 2) +let result3 = Int.Bitwise.lxor(1, 2) +let result4 = Int.Bitwise.lsl(1, 2) +let result5 = Int.Bitwise.lsr(1, 2) +let result6 = Int.Bitwise.asr(1, 2) +let result7 = Int.Bitwise.lnot(0) diff --git a/tests/tools_tests/src/migrate/StdlibMigration_JSON.res b/tests/tools_tests/src/migrate/StdlibMigration_JSON.res new file mode 100644 index 0000000000..60e13379a2 --- /dev/null +++ b/tests/tools_tests/src/migrate/StdlibMigration_JSON.res @@ -0,0 +1,11 @@ +external someJson: Js_json.t = "someJson" +external strToJson: string => Js_json.t = "strToJson" + +let decodeString1 = someJson->Js_json.decodeString +let decodeString2 = Js_json.decodeString(someJson) +let decodeString3 = + [1, 2, 3] + ->Array.map(v => v->Int.toString) + ->Array.join(" ") + ->strToJson + ->Js_json.decodeString diff --git a/tests/tools_tests/src/migrate/StdlibMigration_Js.res b/tests/tools_tests/src/migrate/StdlibMigration_Js.res new file mode 100644 index 0000000000..39deedf002 --- /dev/null +++ b/tests/tools_tests/src/migrate/StdlibMigration_Js.res @@ -0,0 +1,5 @@ +let consoleLog1 = Js.log("Hello") +let consoleLog2 = Js.log2("Hello", "World") +let consoleLog3 = Js.log3("Hello", "World", "!") +let consoleLog4 = Js.log4("Hello", "World", "!", "!") +let consoleLogMany = Js.logMany(["Hello", "World"]) diff --git a/tests/tools_tests/src/migrate/StdlibMigration_String.res b/tests/tools_tests/src/migrate/StdlibMigration_String.res new file mode 100644 index 0000000000..a67821e71f --- /dev/null +++ b/tests/tools_tests/src/migrate/StdlibMigration_String.res @@ -0,0 +1,125 @@ +let make1 = 1->Js.String2.make +let make2 = Js.String2.make(1) + +let fromCharCode1 = 65->Js.String2.fromCharCode +let fromCharCode2 = Js.String2.fromCharCode(65) + +let fromCharCodeMany1 = [65, 66, 67]->Js.String2.fromCharCodeMany +let fromCharCodeMany2 = Js.String2.fromCharCodeMany([65, 66, 67]) + +let fromCodePoint1 = 65->Js.String2.fromCodePoint +let fromCodePoint2 = Js.String2.fromCodePoint(65) + +let fromCodePointMany1 = [65, 66, 67]->Js.String2.fromCodePointMany +let fromCodePointMany2 = Js.String2.fromCodePointMany([65, 66, 67]) + +let length1 = "abcde"->Js.String2.length +let length2 = Js.String2.length("abcde") + +let get1 = "abcde"->Js.String2.get(2) +let get2 = Js.String2.get("abcde", 2) + +let charAt1 = "abcde"->Js.String2.charAt(2) +let charAt2 = Js.String2.charAt("abcde", 2) + +let charCodeAt1 = "abcde"->Js.String2.charCodeAt(2) +let charCodeAt2 = Js.String2.charCodeAt("abcde", 2) + +let codePointAt1 = "abcde"->Js.String2.codePointAt(2) +let codePointAt2 = Js.String2.codePointAt("abcde", 2) + +let concat1 = "abcde"->Js.String2.concat("fghij") +let concat2 = Js.String2.concat("abcde", "fghij") + +let concatMany1 = "abcde"->Js.String2.concatMany(["fghij", "klmno"]) +let concatMany2 = Js.String2.concatMany("abcde", ["fghij", "klmno"]) + +let endsWith1 = "abcde"->Js.String2.endsWith("de") +let endsWith2 = Js.String2.endsWith("abcde", "de") + +let endsWithFrom1 = "abcde"->Js.String2.endsWithFrom("d", 2) +let endsWithFrom2 = Js.String2.endsWithFrom("abcde", "d", 2) + +let includes1 = "abcde"->Js.String2.includes("de") +let includes2 = Js.String2.includes("abcde", "de") + +let includesFrom1 = "abcde"->Js.String2.includesFrom("d", 2) +let includesFrom2 = Js.String2.includesFrom("abcde", "d", 2) + +let indexOf1 = "abcde"->Js.String2.indexOf("de") +let indexOf2 = Js.String2.indexOf("abcde", "de") + +let indexOfFrom1 = "abcde"->Js.String2.indexOfFrom("d", 2) +let indexOfFrom2 = Js.String2.indexOfFrom("abcde", "d", 2) + +let lastIndexOf1 = "abcde"->Js.String2.lastIndexOf("de") +let lastIndexOf2 = Js.String2.lastIndexOf("abcde", "de") + +let lastIndexOfFrom1 = "abcde"->Js.String2.lastIndexOfFrom("d", 2) +let lastIndexOfFrom2 = Js.String2.lastIndexOfFrom("abcde", "d", 2) + +let localeCompare1 = "abcde"->Js.String2.localeCompare("fghij") +let localeCompare2 = Js.String2.localeCompare("abcde", "fghij") + +let match1 = "abcde"->Js.String2.match_(/d/) +let match2 = Js.String2.match_("abcde", /d/) + +let normalize1 = "abcde"->Js.String2.normalize +let normalize2 = Js.String2.normalize("abcde") + +let repeat1 = "abcde"->Js.String2.repeat(2) +let repeat2 = Js.String2.repeat("abcde", 2) + +let replace1 = "abcde"->Js.String2.replace("d", "f") +let replace2 = Js.String2.replace("abcde", "d", "f") + +let replaceByRe1 = "abcde"->Js.String2.replaceByRe(/d/, "f") +let replaceByRe2 = Js.String2.replaceByRe("abcde", /d/, "f") + +let search1 = "abcde"->Js.String2.search(/d/) +let search2 = Js.String2.search("abcde", /d/) + +let slice1 = "abcde"->Js.String2.slice(~from=1, ~to_=3) +let slice2 = Js.String2.slice("abcde", ~from=1, ~to_=3) + +let sliceToEnd1 = "abcde"->Js.String2.sliceToEnd(~from=1) +let sliceToEnd2 = Js.String2.sliceToEnd("abcde", ~from=1) + +let split1 = "abcde"->Js.String2.split("d") +let split2 = Js.String2.split("abcde", "d") + +let splitAtMost1 = "abcde"->Js.String2.splitAtMost("d", ~limit=2) +let splitAtMost2 = Js.String2.splitAtMost("abcde", "d", ~limit=2) + +let splitByRe1 = "abcde"->Js.String2.splitByRe(/d/) +let splitByRe2 = Js.String2.splitByRe("abcde", /d/) + +let splitByReAtMost1 = "abcde"->Js.String2.splitByReAtMost(/d/, ~limit=2) +let splitByReAtMost2 = Js.String2.splitByReAtMost("abcde", /d/, ~limit=2) + +let startsWith1 = "abcde"->Js.String2.startsWith("ab") +let startsWith2 = Js.String2.startsWith("abcde", "ab") + +let startsWithFrom1 = "abcde"->Js.String2.startsWithFrom("b", 1) +let startsWithFrom2 = Js.String2.startsWithFrom("abcde", "b", 1) + +let substring1 = "abcde"->Js.String2.substring(~from=1, ~to_=3) +let substring2 = Js.String2.substring("abcde", ~from=1, ~to_=3) + +let substringToEnd1 = "abcde"->Js.String2.substringToEnd(~from=1) +let substringToEnd2 = Js.String2.substringToEnd("abcde", ~from=1) + +let toLowerCase1 = "abcde"->Js.String2.toLowerCase +let toLowerCase2 = Js.String2.toLowerCase("abcde") + +let toLocaleLowerCase1 = "abcde"->Js.String2.toLocaleLowerCase +let toLocaleLowerCase2 = Js.String2.toLocaleLowerCase("abcde") + +let toUpperCase1 = "abcde"->Js.String2.toUpperCase +let toUpperCase2 = Js.String2.toUpperCase("abcde") + +let toLocaleUpperCase1 = "abcde"->Js.String2.toLocaleUpperCase +let toLocaleUpperCase2 = Js.String2.toLocaleUpperCase("abcde") + +let trim1 = "abcde"->Js.String2.trim +let trim2 = Js.String2.trim("abcde") diff --git a/tests/tools_tests/src/migrate/migrated/Migrated_StdlibMigration_Array.res b/tests/tools_tests/src/migrate/migrated/Migrated_StdlibMigration_Array.res new file mode 100644 index 0000000000..52a6757808 --- /dev/null +++ b/tests/tools_tests/src/migrate/migrated/Migrated_StdlibMigration_Array.res @@ -0,0 +1,170 @@ +// This file is autogenerated so it can be type checked. +// It's the migrated version of src/migrate/StdlibMigration_Array.res. +let shift1 = [1, 2, 3]->Array.shift +let shift2 = Array.shift([1, 2, 3]) + +let slice1 = [1, 2, 3]->Array.slice(~start=1, ~end=2) +let slice2 = Array.slice([1, 2, 3], ~start=1, ~end=2) + +external someArrayLike: Js_array2.array_like = "whatever" + +let from1 = someArrayLike->Array.fromArrayLike +let from2 = Array.fromArrayLike(someArrayLike) + +let fromMap1 = someArrayLike->Array.fromArrayLikeWithMap(s => s ++ "!") +let fromMap2 = Array.fromArrayLikeWithMap(someArrayLike, s => s ++ "!") + +let isArray1 = [1, 2, 3]->Array.isArray +let isArray2 = Array.isArray([1, 2, 3]) + +let length1 = [1, 2, 3]->Array.length +let length2 = Array.length([1, 2, 3]) + +let fillInPlace1 = [1, 2, 3]->Array.fillAll(0) +let fillInPlace2 = Array.fillAll([1, 2, 3], 0) + +let fillFromInPlace1 = [1, 2, 3, 4]->Array.fillToEnd(0, ~start=2) +let fillFromInPlace2 = Array.fillToEnd([1, 2, 3, 4], 0, ~start=2) + +let fillRangeInPlace1 = [1, 2, 3, 4]->Array.fill(0, ~start=1, ~end=3) +let fillRangeInPlace2 = Array.fill([1, 2, 3, 4], 0, ~start=1, ~end=3) + +let pop1 = [1, 2, 3]->Array.pop +let pop2 = Array.pop([1, 2, 3]) + +let reverseInPlace1 = [1, 2, 3]->Array.reverse +let reverseInPlace2 = Array.reverse([1, 2, 3]) + +let concat1 = [1, 2]->Array.concat([3, 4]) +let concat2 = Array.concat([1, 2], [3, 4]) + +let concatMany1 = [1, 2]->Array.concatMany([[3, 4], [5, 6]]) +let concatMany2 = Array.concatMany([1, 2], [[3, 4], [5, 6]]) + +let includes1 = [1, 2, 3]->Array.includes(2) +let includes2 = Array.includes([1, 2, 3], 2) + +let indexOf1 = [1, 2, 3]->Array.indexOf(2) +let indexOf2 = Array.indexOf([1, 2, 3], 2) + +let indexOfFrom1 = [1, 2, 1, 3]->Array.indexOfFrom(1, 2) +let indexOfFrom2 = Array.indexOfFrom([1, 2, 1, 3], 1, 2) + +let joinWith1 = [1, 2, 3]->Array.joinUnsafe(",") +let joinWith2 = Array.joinUnsafe([1, 2, 3], ",") + +let lastIndexOf1 = [1, 2, 1, 3]->Array.lastIndexOf(1) +let lastIndexOf2 = Array.lastIndexOf([1, 2, 1, 3], 1) + +let lastIndexOfFrom1 = [1, 2, 1, 3, 1]->Array.lastIndexOfFrom(1, 3) +let lastIndexOfFrom2 = Array.lastIndexOfFrom([1, 2, 1, 3, 1], 1, 3) + +let copy1 = [1, 2, 3]->Array.copy +let copy2 = Array.copy([1, 2, 3]) + +let sliceFrom1 = [1, 2, 3, 4]->Array.sliceToEnd(~start=2) +let sliceFrom2 = Array.sliceToEnd([1, 2, 3, 4], ~start=2) + +let toString1 = [1, 2, 3]->Array.toString +let toString2 = Array.toString([1, 2, 3]) + +let toLocaleString1 = [1, 2, 3]->Array.toLocaleString +let toLocaleString2 = Array.toLocaleString([1, 2, 3]) + +let every1 = [2, 4, 6]->Array.every(x => mod(x, 2) == 0) +let every2 = Array.every([2, 4, 6], x => mod(x, 2) == 0) + +let everyi1 = [0, 1, 2]->Array.everyWithIndex((x, i) => x == i) +let everyi2 = Array.everyWithIndex([0, 1, 2], (x, i) => x == i) + +let filter1 = [1, 2, 3, 4]->Array.filter(x => x > 2) +let filter2 = Array.filter([1, 2, 3, 4], x => x > 2) + +let filteri1 = [0, 1, 2, 3]->Array.filterWithIndex((_x, i) => i > 1) +let filteri2 = Array.filterWithIndex([0, 1, 2, 3], (_x, i) => i > 1) + +let find1 = [1, 2, 3, 4]->Array.find(x => x > 2) +let find2 = Array.find([1, 2, 3, 4], x => x > 2) + +let findi1 = [0, 1, 2, 3]->Array.findWithIndex((_x, i) => i > 1) +let findi2 = Array.findWithIndex([0, 1, 2, 3], (_x, i) => i > 1) + +let findIndex1 = [1, 2, 3, 4]->Array.findIndex(x => x > 2) +let findIndex2 = Array.findIndex([1, 2, 3, 4], x => x > 2) + +let findIndexi1 = [0, 1, 2, 3]->Array.findIndexWithIndex((_x, i) => i > 1) +let findIndexi2 = Array.findIndexWithIndex([0, 1, 2, 3], (_x, i) => i > 1) + +let forEach1 = [1, 2, 3]->Array.forEach(x => ignore(x)) +let forEach2 = Array.forEach([1, 2, 3], x => ignore(x)) + +let forEachi1 = [1, 2, 3]->Array.forEachWithIndex((x, i) => ignore(x + i)) +let forEachi2 = Array.forEachWithIndex([1, 2, 3], (x, i) => ignore(x + i)) + +let map1 = [1, 2, 3]->Array.map(x => x * 2) +let map2 = Array.map([1, 2, 3], x => x * 2) + +let mapi1 = [1, 2, 3]->Array.mapWithIndex((x, i) => x + i) +let mapi2 = Array.mapWithIndex([1, 2, 3], (x, i) => x + i) + +let some1 = [1, 2, 3, 4]->Array.some(x => x > 3) +let some2 = Array.some([1, 2, 3, 4], x => x > 3) + +let somei1 = [0, 1, 2, 3]->Array.someWithIndex((_x, i) => i > 2) +let somei2 = Array.someWithIndex([0, 1, 2, 3], (_x, i) => i > 2) + +let unsafeGet1 = [1, 2, 3]->Array.getUnsafe(1) +let unsafeGet2 = Array.getUnsafe([1, 2, 3], 1) + +let unsafeSet1 = [1, 2, 3]->Array.setUnsafe(1, 5) +let unsafeSet2 = Array.setUnsafe([1, 2, 3], 1, 5) + +let copyWithin1 = [1, 2, 3, 4, 5]->Array.copyAllWithin(~target=2) +let copyWithin2 = Array.copyAllWithin([1, 2, 3, 4, 5], ~target=2) + +let copyWithinFrom1 = [1, 2, 3, 4, 5]->Array.copyWithinToEnd(~target=0, ~start=2) +let copyWithinFrom2 = Array.copyWithinToEnd([1, 2, 3, 4, 5], ~target=0, ~start=2) + +let copyWithinFromRange1 = [1, 2, 3, 4, 5, 6]->Array.copyWithin(~target=1, ~start=2, ~end=5) +let copyWithinFromRange2 = Array.copyWithin([1, 2, 3, 4, 5, 6], ~target=1, ~start=2, ~end=5) + +let push1 = [1, 2, 3]->Array.push(4) +let push2 = Array.push([1, 2, 3], 4) + +let pushMany1 = [1, 2, 3]->Array.pushMany([4, 5]) +let pushMany2 = Array.pushMany([1, 2, 3], [4, 5]) + +let sortInPlace1 = + ["c", "a", "b"]->Array.toSorted((a, b) => + %todo("This needs a comparator function. Use `String.compare` for strings, etc.") + ) +let sortInPlace2 = Array.toSorted(["c", "a", "b"], (a, b) => + %todo("This needs a comparator function. Use `String.compare` for strings, etc.") +) + +let unshift1 = [1, 2, 3]->Array.unshift(4) +let unshift2 = Array.unshift([1, 2, 3], 4) + +let unshiftMany1 = [1, 2, 3]->Array.unshiftMany([4, 5]) +let unshiftMany2 = Array.unshiftMany([1, 2, 3], [4, 5]) + +let reduce1 = [1, 2, 3]->Array.reduce(0, (acc, x) => acc + x) +let reduce2 = Array.reduce([1, 2, 3], 0, (acc, x) => acc + x) + +let spliceInPlace1 = [1, 2, 3]->Array.splice(~start=1, ~remove=1, ~insert=[4, 5]) +let spliceInPlace2 = Array.splice([1, 2, 3], ~start=1, ~remove=1, ~insert=[4, 5]) + +let removeFromInPlace1 = [1, 2, 3]->Array.removeInPlace(1) +let removeFromInPlace2 = Array.removeInPlace([1, 2, 3], 1) + +let removeCountInPlace1 = [1, 2, 3]->Array.splice(~start=1, ~remove=1, ~insert=[]) +let removeCountInPlace2 = Array.splice([1, 2, 3], ~start=1, ~remove=1, ~insert=[]) + +let reducei1 = [1, 2, 3]->Array.reduceWithIndex(0, (acc, x, i) => acc + x + i) +let reducei2 = Array.reduceWithIndex([1, 2, 3], 0, (acc, x, i) => acc + x + i) + +let reduceRight1 = [1, 2, 3]->Array.reduceRight(0, (acc, x) => acc + x) +let reduceRight2 = Array.reduceRight([1, 2, 3], 0, (acc, x) => acc + x) + +let reduceRighti1 = [1, 2, 3]->Array.reduceRightWithIndex(0, (acc, x, i) => acc + x + i) +let reduceRighti2 = Array.reduceRightWithIndex([1, 2, 3], 0, (acc, x, i) => acc + x + i) diff --git a/tests/tools_tests/src/migrate/migrated/Migrated_StdlibMigration_BigInt.res b/tests/tools_tests/src/migrate/migrated/Migrated_StdlibMigration_BigInt.res new file mode 100644 index 0000000000..3ea3562f5d --- /dev/null +++ b/tests/tools_tests/src/migrate/migrated/Migrated_StdlibMigration_BigInt.res @@ -0,0 +1,49 @@ +// This file is autogenerated so it can be type checked. +// It's the migrated version of src/migrate/StdlibMigration_BigInt.res. +let fromStringExn1 = "123"->BigInt.fromStringOrThrow +let fromStringExn2 = BigInt.fromStringOrThrow("123") + +let land1 = 7n->BigInt.bitwiseAnd(4n) +let land2 = 7n & 4n + +let lor1 = 7n->BigInt.bitwiseOr(4n) +let lor2 = BigInt.bitwiseOr(7n, 4n) + +let lxor1 = 7n->BigInt.bitwiseXor(4n) +let lxor2 = 7n ^ 4n + +let lnot1 = 2n->Js.BigInt.lnot +let lnot2 = Js.BigInt.lnot(2n) + +let lsl1 = 4n->BigInt.shiftLeft(1n) +let lsl2 = 4n << 1n + +let asr1 = 8n->BigInt.shiftRight(1n) +let asr2 = 8n >> 1n + +let toString1 = 123n->BigInt.toString +let toString2 = BigInt.toString(123n) + +let toLocaleString1 = 123n->BigInt.toLocaleString +let toLocaleString2 = BigInt.toLocaleString(123n) + +// From the stdlib module +let stdlib_fromStringExn1 = "123"->BigInt.fromStringOrThrow +let stdlib_fromStringExn2 = BigInt.fromStringOrThrow("123") + +let stdlib_land1 = 7n->BigInt.bitwiseAnd(4n) +let stdlib_land2 = 7n & 4n + +let stdlib_lor1 = BigInt.bitwiseOr(7n, 4n) + +let stdlib_lxor1 = 7n->BigInt.bitwiseXor(4n) +let stdlib_lxor2 = 7n ^ 4n + +let stdlib_lnot1 = 2n->BigInt.bitwiseNot +let stdlib_lnot2 = ~2n + +let stdlib_lsl1 = 4n->BigInt.shiftLeft(1n) +let stdlib_lsl2 = 4n << 1n + +let stdlib_asr1 = 8n->BigInt.shiftRight(1n) +let stdlib_asr2 = 8n >> 1n diff --git a/tests/tools_tests/src/migrate/migrated/Migrated_StdlibMigration_Console.res b/tests/tools_tests/src/migrate/migrated/Migrated_StdlibMigration_Console.res new file mode 100644 index 0000000000..d539a85560 --- /dev/null +++ b/tests/tools_tests/src/migrate/migrated/Migrated_StdlibMigration_Console.res @@ -0,0 +1,30 @@ +// This file is autogenerated so it can be type checked. +// It's the migrated version of src/migrate/StdlibMigration_Console.res. +let log = Console.log("Hello, World!") +let log2 = Console.log2("Hello", "World") +let log3 = Console.log3("Hello", "World", "!") +let log4 = Console.log4("Hello", "World", "!", "!") +let logMany = Console.logMany(["Hello", "World"]) + +let info = Console.info("Hello, World!") +let info2 = Console.info2("Hello", "World") +let info3 = Console.info3("Hello", "World", "!") +let info4 = Console.info4("Hello", "World", "!", "!") +let infoMany = Console.infoMany(["Hello", "World"]) + +let warn = Console.warn("Hello, World!") +let warn2 = Console.warn2("Hello", "World") +let warn3 = Console.warn3("Hello", "World", "!") +let warn4 = Console.warn4("Hello", "World", "!", "!") +let warnMany = Console.warnMany(["Hello", "World"]) + +let error = Console.error("Hello, World!") +let error2 = Console.error2("Hello", "World") +let error3 = Console.error3("Hello", "World", "!") +let error4 = Console.error4("Hello", "World", "!", "!") +let errorMany = Console.errorMany(["Hello", "World"]) + +let trace = Console.trace() +let timeStart = Console.time("Hello, World!") +let timeEnd = Console.timeEnd("Hello, World!") +let table = Console.table(["Hello", "World"]) diff --git a/tests/tools_tests/src/migrate/migrated/Migrated_StdlibMigration_Int.res b/tests/tools_tests/src/migrate/migrated/Migrated_StdlibMigration_Int.res new file mode 100644 index 0000000000..43b70137c8 --- /dev/null +++ b/tests/tools_tests/src/migrate/migrated/Migrated_StdlibMigration_Int.res @@ -0,0 +1,9 @@ +// This file is autogenerated so it can be type checked. +// It's the migrated version of src/migrate/StdlibMigration_Int.res. +let result1 = Int.bitwiseAnd(1, 2) +let result2 = Int.bitwiseOr(1, 2) +let result3 = Int.bitwiseXor(1, 2) +let result4 = Int.shiftLeft(1, 2) +let result5 = Int.shiftRightUnsigned(1, 2) +let result6 = Int.shiftRight(1, 2) +let result7 = Int.bitwiseNot(0) diff --git a/tests/tools_tests/src/migrate/migrated/Migrated_StdlibMigration_JSON.res b/tests/tools_tests/src/migrate/migrated/Migrated_StdlibMigration_JSON.res new file mode 100644 index 0000000000..103bd0109c --- /dev/null +++ b/tests/tools_tests/src/migrate/migrated/Migrated_StdlibMigration_JSON.res @@ -0,0 +1,20 @@ +// This file is autogenerated so it can be type checked. +// It's the migrated version of src/migrate/StdlibMigration_JSON.res. +external someJson: Js_json.t = "someJson" +external strToJson: string => Js_json.t = "strToJson" + +let decodeString1 = switch someJson { +| JSON.String(str) => Some(str) +| _ => None +} +let decodeString2 = switch someJson { +| JSON.String(str) => Some(str) +| _ => None +} +let decodeString3 = switch [1, 2, 3] +->Array.map(v => v->Int.toString) +->Array.join(" ") +->strToJson { +| JSON.String(str) => Some(str) +| _ => None +} diff --git a/tests/tools_tests/src/migrate/migrated/Migrated_StdlibMigration_Js.res b/tests/tools_tests/src/migrate/migrated/Migrated_StdlibMigration_Js.res new file mode 100644 index 0000000000..87922b7521 --- /dev/null +++ b/tests/tools_tests/src/migrate/migrated/Migrated_StdlibMigration_Js.res @@ -0,0 +1,7 @@ +// This file is autogenerated so it can be type checked. +// It's the migrated version of src/migrate/StdlibMigration_Js.res. +let consoleLog1 = Console.log("Hello") +let consoleLog2 = Console.log2("Hello", "World") +let consoleLog3 = Console.log3("Hello", "World", "!") +let consoleLog4 = Console.log4("Hello", "World", "!", "!") +let consoleLogMany = Console.logMany(["Hello", "World"]) diff --git a/tests/tools_tests/src/migrate/migrated/Migrated_StdlibMigration_String.res b/tests/tools_tests/src/migrate/migrated/Migrated_StdlibMigration_String.res new file mode 100644 index 0000000000..9e67e14937 --- /dev/null +++ b/tests/tools_tests/src/migrate/migrated/Migrated_StdlibMigration_String.res @@ -0,0 +1,127 @@ +// This file is autogenerated so it can be type checked. +// It's the migrated version of src/migrate/StdlibMigration_String.res. +let make1 = 1->String.make +let make2 = String.make(1) + +let fromCharCode1 = 65->String.fromCharCode +let fromCharCode2 = String.fromCharCode(65) + +let fromCharCodeMany1 = [65, 66, 67]->String.fromCharCodeMany +let fromCharCodeMany2 = String.fromCharCodeMany([65, 66, 67]) + +let fromCodePoint1 = 65->String.fromCodePoint +let fromCodePoint2 = String.fromCodePoint(65) + +let fromCodePointMany1 = [65, 66, 67]->String.fromCodePointMany +let fromCodePointMany2 = String.fromCodePointMany([65, 66, 67]) + +let length1 = "abcde"->String.length +let length2 = String.length("abcde") + +let get1 = "abcde"->String.getUnsafe(2) +let get2 = String.getUnsafe("abcde", 2) + +let charAt1 = "abcde"->String.charAt(2) +let charAt2 = String.charAt("abcde", 2) + +let charCodeAt1 = "abcde"->String.charCodeAt(2) +let charCodeAt2 = String.charCodeAt("abcde", 2) + +let codePointAt1 = "abcde"->String.codePointAt(2) +let codePointAt2 = String.codePointAt("abcde", 2) + +let concat1 = "abcde"->String.concat("fghij") +let concat2 = String.concat("abcde", "fghij") + +let concatMany1 = "abcde"->String.concatMany(["fghij", "klmno"]) +let concatMany2 = String.concatMany("abcde", ["fghij", "klmno"]) + +let endsWith1 = "abcde"->String.endsWith("de") +let endsWith2 = String.endsWith("abcde", "de") + +let endsWithFrom1 = "abcde"->String.endsWithFrom("d", 2) +let endsWithFrom2 = String.endsWithFrom("abcde", "d", 2) + +let includes1 = "abcde"->String.includes("de") +let includes2 = String.includes("abcde", "de") + +let includesFrom1 = "abcde"->String.includesFrom("d", 2) +let includesFrom2 = String.includesFrom("abcde", "d", 2) + +let indexOf1 = "abcde"->String.indexOf("de") +let indexOf2 = String.indexOf("abcde", "de") + +let indexOfFrom1 = "abcde"->String.indexOfFrom("d", 2) +let indexOfFrom2 = String.indexOfFrom("abcde", "d", 2) + +let lastIndexOf1 = "abcde"->String.lastIndexOf("de") +let lastIndexOf2 = String.lastIndexOf("abcde", "de") + +let lastIndexOfFrom1 = "abcde"->String.lastIndexOfFrom("d", 2) +let lastIndexOfFrom2 = String.lastIndexOfFrom("abcde", "d", 2) + +let localeCompare1 = "abcde"->String.localeCompare("fghij") +let localeCompare2 = String.localeCompare("abcde", "fghij") + +let match1 = "abcde"->String.match(/d/) +let match2 = String.match("abcde", /d/) + +let normalize1 = "abcde"->String.normalize +let normalize2 = String.normalize("abcde") + +let repeat1 = "abcde"->String.repeat(2) +let repeat2 = String.repeat("abcde", 2) + +let replace1 = "abcde"->String.replace("d", "f") +let replace2 = String.replace("abcde", "d", "f") + +let replaceByRe1 = "abcde"->String.replaceRegExp(/d/, "f") +let replaceByRe2 = String.replaceRegExp("abcde", /d/, "f") + +let search1 = "abcde"->String.search(/d/) +let search2 = String.search("abcde", /d/) + +let slice1 = "abcde"->String.slice(~start=1, ~end=3) +let slice2 = String.slice("abcde", ~start=1, ~end=3) + +let sliceToEnd1 = "abcde"->String.sliceToEnd(~start=1) +let sliceToEnd2 = String.sliceToEnd("abcde", ~start=1) + +let split1 = "abcde"->String.split("d") +let split2 = String.split("abcde", "d") + +let splitAtMost1 = "abcde"->String.splitAtMost("d", ~limit=2) +let splitAtMost2 = String.splitAtMost("abcde", "d", ~limit=2) + +let splitByRe1 = "abcde"->String.splitByRegExp(/d/) +let splitByRe2 = String.splitByRegExp("abcde", /d/) + +let splitByReAtMost1 = "abcde"->String.splitByRegExpAtMost(/d/, ~limit=2) +let splitByReAtMost2 = String.splitByRegExpAtMost("abcde", /d/, ~limit=2) + +let startsWith1 = "abcde"->String.startsWith("ab") +let startsWith2 = String.startsWith("abcde", "ab") + +let startsWithFrom1 = "abcde"->String.startsWithFrom("b", 1) +let startsWithFrom2 = String.startsWithFrom("abcde", "b", 1) + +let substring1 = "abcde"->String.substring(~start=1, ~end=3) +let substring2 = String.substring("abcde", ~start=1, ~end=3) + +let substringToEnd1 = "abcde"->String.substringToEnd(~start=1) +let substringToEnd2 = String.substringToEnd("abcde", ~start=1) + +let toLowerCase1 = "abcde"->String.toLowerCase +let toLowerCase2 = String.toLowerCase("abcde") + +let toLocaleLowerCase1 = "abcde"->String.toLocaleLowerCase +let toLocaleLowerCase2 = String.toLocaleLowerCase("abcde") + +let toUpperCase1 = "abcde"->String.toUpperCase +let toUpperCase2 = String.toUpperCase("abcde") + +let toLocaleUpperCase1 = "abcde"->String.toLocaleUpperCase +let toLocaleUpperCase2 = String.toLocaleUpperCase("abcde") + +let trim1 = "abcde"->String.trim +let trim2 = String.trim("abcde") diff --git a/tests/tools_tests/test.sh b/tests/tools_tests/test.sh index 73e42acfd6..4e44f42170 100755 --- a/tests/tools_tests/test.sh +++ b/tests/tools_tests/test.sh @@ -33,6 +33,24 @@ for file in src/docstrings-format/*.{res,resi,md}; do fi done +# Test migrate command +for file in src/migrate/*.{res,resi}; do + output="src/expected/$(basename $file).expected" + ../../_build/install/default/bin/rescript-tools migrate "$file" --stdout > $output + if [ "$RUNNER_OS" == "Windows" ]; then + perl -pi -e 's/\r\n/\n/g' -- $output + fi +done + +# Move migrated files to expected directory so they can be compiled in the project +for file in src/migrate/StdlibMigration_*.res; do + expected_file="src/expected/$(basename $file).expected" + output="src/migrate/migrated/Migrated_$(basename $file)" + echo "// This file is autogenerated so it can be type checked. +// It's the migrated version of $file." > "$output" && cat "$expected_file" >> "$output" + ../../cli/rescript.js format "$output" +done + warningYellow='\033[0;33m' successGreen='\033[0;32m' reset='\033[0m' diff --git a/tools/bin/main.ml b/tools/bin/main.ml index 88f7ffa575..6f1a76ff45 100644 --- a/tools/bin/main.ml +++ b/tools/bin/main.ml @@ -32,6 +32,7 @@ Usage: rescript-tools [command] Commands: +migrate [--stdout] Runs the migration tool on the given file doc Generate documentation format-codeblocks Format ReScript code blocks [--stdout] Output to stdout @@ -66,6 +67,15 @@ let main () = in logAndExit (Tools.extractDocs ~entryPointFile:path ~debug:false) | _ -> logAndExit (Error docHelp)) + | "migrate" :: file :: opts -> ( + let isStdout = List.mem "--stdout" opts in + let outputMode = if isStdout then `Stdout else `File in + match + (Tools.Migrate.migrate ~entryPointFile:file ~outputMode, outputMode) + with + | Ok content, `Stdout -> print_endline content + | result, `File -> logAndExit result + | Error e, _ -> logAndExit (Error e)) | "format-codeblocks" :: rest -> ( match rest with | ["-h"] | ["--help"] -> logAndExit (Ok formatCodeblocksHelp) diff --git a/tools/src/tools.ml b/tools/src/tools.ml index 1722fdda07..aafdaba331 100644 --- a/tools/src/tools.ml +++ b/tools/src/tools.ml @@ -1292,3 +1292,591 @@ module ExtractCodeblocks = struct ]) |> Protocol.array) end + +module StringMap = Map.Make (String) + +module Migrate = struct + (* + Currently, the migrate command can handle: + - Function calls, including mapping labelled/optional arguments between calls. Piped and not piped. + + It _cannot_ (among much else) handle: + - Changing position of unlabelled arguments (would be problematic with pipes etc) + *) + + (* + TODO: + - Migrate type usage (Js.Array2.t -> array, etc) + - Add "migratePipe" for specific migrations of pipe calls, like `BigInt.land` that can be `&` when not piped, but needs to be `BigInt.bitwiseAnd` when piped. + *) + + module MapperUtils = struct + let get_template_args_to_insert ?(is_pipe = false) mapper template_args + source_args = + let labelled_args_that_will_be_mapped = ref [] in + let unlabelled_positions_that_will_be_mapped = ref [] in + let mapped_template_args = + template_args + |> List.filter_map (fun (label, arg) -> + match (label, arg) with + | ( Asttypes.Nolabel, + { + Parsetree.pexp_desc = + Pexp_extension + ( {txt = "insert.labelledArgument"}, + PStr + [ + { + pstr_desc = + Pstr_eval + ( { + pexp_desc = + Pexp_constant + (Pconst_string (arg_name, _)); + }, + _ ); + }; + ] ); + } ) -> ( + (* Map labelled args *) + let arg_in_source_args = + source_args + |> List.find_map (fun (label, arg) -> + match label with + | Asttypes.Labelled {txt = label} + | Optional {txt = label} -> + if label = arg_name then Some arg else None + | _ -> None) + in + match arg_in_source_args with + | None -> None + | Some arg -> + labelled_args_that_will_be_mapped := + arg_name :: !labelled_args_that_will_be_mapped; + Some (Asttypes.Nolabel, arg)) + | ( template_label, + { + Parsetree.pexp_desc = + Pexp_extension + ( {txt = "insert.unlabelledArgument"}, + PStr + [ + { + pstr_desc = + Pstr_eval + ( { + pexp_desc = + Pexp_constant + (Pconst_integer (count_str, _)); + }, + _ ); + }; + ] ); + } ) -> ( + (* Map unlabelled args *) + let count = int_of_string count_str in + if count <= 0 then None + else + (* Count unlabelled arguments properly: + - For regular calls: count=1 refers to 2nd unlabelled arg (since 1st can't be remapped due to pipes) + - For pipe calls: count=1 refers to 1st unlabelled arg in pipe_args *) + let target_count = if is_pipe then count else count + 1 in + let unlabelled_count = ref 0 in + let found_arg = ref None in + source_args + |> List.iter (fun (label, arg) -> + match label with + | Asttypes.Nolabel -> + incr unlabelled_count; + if !unlabelled_count = target_count then + found_arg := Some arg + | _ -> ()); + match !found_arg with + | None -> None + | Some arg -> + unlabelled_positions_that_will_be_mapped := + target_count :: !unlabelled_positions_that_will_be_mapped; + Some (template_label, arg)) + | ( _, + { + pexp_desc = + Pexp_extension + ( { + txt = + ( "insert.labelledArgument" + | "insert.unlabelledArgument" ); + }, + _ ); + } ) -> + (* Do not add any other instance of insert.* *) + None + | _, {pexp_desc = Pexp_construct ({txt = Lident "()"}, None)} -> + None + | _ -> Some (label, mapper.Ast_mapper.expr mapper arg)) + in + ( mapped_template_args, + !labelled_args_that_will_be_mapped, + !unlabelled_positions_that_will_be_mapped ) + + let filter_and_transform_args source_args ~unlabelled_positions_to_insert + ~will_be_mapped ~labelled_args_map = + let unlabelled_consumed = ref 0 in + source_args + |> List.filter_map (fun (label, arg) -> + match label with + | Asttypes.Nolabel -> + incr unlabelled_consumed; + if List.mem !unlabelled_consumed unlabelled_positions_to_insert + then + (* This unlabelled arg has been mapped already, do not add. *) + None + else Some (label, arg) + | Asttypes.Labelled {loc; txt = label} + | Optional {loc; txt = label} + when StringMap.mem label labelled_args_map -> + (* Map labelled args that has just changed name. *) + let mapped_label_name = StringMap.find label labelled_args_map in + Some (Asttypes.Labelled {loc; txt = mapped_label_name}, arg) + | (Labelled {txt} | Optional {txt}) + when List.mem txt will_be_mapped -> + (* These have been mapped already, do not add. *) + None + | label -> Some (label, arg)) + + let build_labelled_args_map template_args = + template_args + |> List.filter_map (fun (label, arg) -> + match (label, arg) with + | ( (Asttypes.Labelled {txt = label} | Optional {txt = label}), + { + Parsetree.pexp_desc = + Pexp_extension + ( {txt = "insert.labelledArgument"}, + PStr + [ + { + pstr_desc = + Pstr_eval + ( { + pexp_desc = + Pexp_constant + (Pconst_string (arg_name, _)); + }, + _ ); + }; + ] ); + } ) -> + Some (arg_name, label) + | _ -> None) + |> List.fold_left + (fun map (k, v) -> StringMap.add k v map) + StringMap.empty + + let apply_migration_template ?(is_pipe = false) mapper template_args + source_args = + let labelled_args_map = build_labelled_args_map template_args in + let ( template_args_to_insert, + will_be_mapped, + unlabelled_positions_to_insert ) = + get_template_args_to_insert ~is_pipe mapper template_args source_args + in + let filtered_args = + filter_and_transform_args source_args ~unlabelled_positions_to_insert + ~will_be_mapped ~labelled_args_map + in + filtered_args @ template_args_to_insert + end + + (* Finds a specific argument in a list of arguments. *) + let find_arg args (find_this_arg : [`Labelled of string | `Unlabelled of int]) + = + let unlabelled_count = ref 0 in + args + |> List.find_map (fun (lbl, arg) -> + match (find_this_arg, lbl) with + | ( `Labelled arg_name, + (Asttypes.Labelled {txt = label} | Optional {txt = label}) ) + when label = arg_name -> + Some (lbl, arg) + | `Unlabelled count, Nolabel -> + let current_count = !unlabelled_count in + incr unlabelled_count; + if current_count = count then Some (lbl, arg) else None + | _, Nolabel -> + incr unlabelled_count; + None + | _ -> None) + + let replace_from_args_in_expr expr source_args = + let mapper = + { + Ast_mapper.default_mapper with + expr = + (fun mapper exp -> + match exp with + | { + pexp_desc = + Pexp_extension + ( {txt = "insert.labelledArgument"}, + PStr + [ + { + pstr_desc = + Pstr_eval + ( { + pexp_desc = + Pexp_constant (Pconst_string (arg_name, _)); + }, + _ ); + }; + ] ); + } -> ( + match find_arg source_args (`Labelled arg_name) with + | Some (_, arg) -> arg + | None -> exp) + | { + pexp_desc = + Pexp_extension + ( {txt = "insert.unlabelledArgument"}, + PStr + [ + { + pstr_desc = + Pstr_eval + ( { + pexp_desc = + Pexp_constant (Pconst_integer (count_str, _)); + }, + _ ); + }; + ] ); + } -> ( + match + find_arg source_args (`Unlabelled (int_of_string count_str)) + with + | Some (_, arg) -> arg + | None -> exp) + | _ -> Ast_mapper.default_mapper.expr mapper exp); + } + in + mapper.expr mapper expr + + let makeMapper (deprecated_used : Cmt_utils.deprecated_used list) = + (* Function calls *) + let deprecated_function_calls = + deprecated_used + |> List.filter (fun (d : Cmt_utils.deprecated_used) -> + match d.context with + | Some FunctionCall -> true + | _ -> false) + in + let loc_to_deprecated_fn_call = + Hashtbl.create (List.length deprecated_function_calls) + in + deprecated_function_calls + |> List.iter (fun ({Cmt_utils.source_loc} as d) -> + Hashtbl.replace loc_to_deprecated_fn_call source_loc d); + + (* References *) + let deprecated_references = + deprecated_used + |> List.filter (fun (d : Cmt_utils.deprecated_used) -> + match d.context with + | Some Reference -> true + | _ -> false) + in + let loc_to_deprecated_reference = + Hashtbl.create (List.length deprecated_references) + in + deprecated_references + |> List.iter (fun ({Cmt_utils.source_loc} as d) -> + Hashtbl.replace loc_to_deprecated_reference source_loc d); + + let mapper = + { + Ast_mapper.default_mapper with + extension = + (fun mapper ext -> + (* Map back %todo_ to %todo, since using %todo directly would result in errors where we don't want them. *) + match ext with + | ({txt = "todo_"} as e), payload -> + Ast_mapper.default_mapper.extension mapper + ({e with txt = "todo"}, payload) + | e -> Ast_mapper.default_mapper.extension mapper e); + expr = + (fun mapper exp -> + match exp with + | {pexp_desc = Pexp_ident {loc}} + when Hashtbl.mem loc_to_deprecated_reference loc -> ( + (* Map references to their migration template. *) + let deprecated_info = + Hashtbl.find loc_to_deprecated_reference loc + in + Hashtbl.remove loc_to_deprecated_reference loc; + match deprecated_info.migration_template with + | None -> exp + | Some e -> e) + | { + pexp_desc = + Pexp_apply {funct = {pexp_loc = fn_loc}; args = source_args}; + } + when Hashtbl.mem loc_to_deprecated_fn_call fn_loc -> ( + let deprecated_info = + Hashtbl.find loc_to_deprecated_fn_call fn_loc + in + Hashtbl.remove loc_to_deprecated_fn_call fn_loc; + + let source_args = + source_args + |> List.map (fun (label, arg) -> + (label, mapper.expr mapper arg)) + in + + (* TODO: Here we could add strict and partial mode, to control if args are merged or not. *) + match deprecated_info.migration_template with + | Some {pexp_desc = Pexp_match (e, cases)} -> + { + exp with + pexp_desc = + Pexp_match (replace_from_args_in_expr e source_args, cases); + } + | Some + { + pexp_desc = + Pexp_apply + { + funct = template_funct; + args = template_args; + partial; + transformed_jsx; + }; + } -> + let migrated_args = + MapperUtils.apply_migration_template mapper template_args + source_args + in + { + exp with + pexp_desc = + Pexp_apply + { + funct = template_funct; + args = migrated_args; + partial; + transformed_jsx; + }; + } + | _ -> + (* TODO: More elaborate warnings etc *) + (* Invalid config. *) + exp) + | { + pexp_desc = + Pexp_apply + { + funct = {pexp_desc = Pexp_ident {txt = Lident "->"}} as funct; + args = + (_ as lhs) + :: (Nolabel, {pexp_loc = fn_loc; pexp_desc = Pexp_ident _}) + :: _; + }; + } + when Hashtbl.mem loc_to_deprecated_fn_call fn_loc -> ( + (* Pipe with no arguments, [1, 2, 3]->someDeprecated + This is the only pipe we need to handle, because the argument one is handled by the transform above. *) + let deprecated_info = + Hashtbl.find loc_to_deprecated_fn_call fn_loc + in + Hashtbl.remove loc_to_deprecated_fn_call fn_loc; + + let migration_template_to_use = + match deprecated_info.migration_piped_template with + | Some template -> Some template + | None -> deprecated_info.migration_template + in + match migration_template_to_use with + | Some {pexp_desc = Pexp_match (e, cases)} -> + { + exp with + pexp_desc = + Pexp_match (replace_from_args_in_expr e [lhs], cases); + } + | Some + { + pexp_desc = + Pexp_apply + { + funct = template_funct; + args = template_args; + partial; + transformed_jsx; + }; + } -> + let template_args_to_insert, _, _ = + MapperUtils.get_template_args_to_insert mapper template_args + [] + in + if Ext_list.is_empty template_args_to_insert then + { + exp with + pexp_desc = + Pexp_apply + { + funct; + args = [lhs; (Nolabel, template_funct)]; + partial; + transformed_jsx; + }; + } + else + { + exp with + pexp_desc = + Pexp_apply + { + funct; + args = + [ + lhs; + ( Nolabel, + Ast_helper.Exp.apply template_funct + template_args_to_insert ); + ]; + partial; + transformed_jsx; + }; + } + | _ -> + (* TODO: More elaborate warnings etc *) + (* Invalid config. *) + exp) + | { + pexp_desc = + Pexp_apply + { + funct = {pexp_desc = Pexp_ident {txt = Lident "->"}} as funct; + args = + (_ as lhs) + :: ( Nolabel, + { + pexp_desc = + Pexp_apply + {funct = {pexp_loc = fn_loc}; args = pipe_args}; + } ) + :: _; + }; + } + when Hashtbl.mem loc_to_deprecated_fn_call fn_loc -> ( + (* Pipe with arguments, [1, 2, 3, 4]->someDeprecated(arg1, arg2) *) + let deprecated_info = + Hashtbl.find loc_to_deprecated_fn_call fn_loc + in + Hashtbl.remove loc_to_deprecated_fn_call fn_loc; + + let migration_template_to_use = + match deprecated_info.migration_piped_template with + | Some template -> Some template + | None -> deprecated_info.migration_template + in + match migration_template_to_use with + | Some + { + pexp_desc = + Pexp_apply + { + funct = template_funct; + args = template_args; + partial; + transformed_jsx; + }; + } -> + let migrated_args = + MapperUtils.apply_migration_template ~is_pipe:true mapper + template_args pipe_args + in + { + exp with + pexp_desc = + Pexp_apply + { + funct; + args = + [ + lhs; + ( Nolabel, + Ast_helper.Exp.apply template_funct migrated_args + ); + ]; + partial; + transformed_jsx; + }; + } + | _ -> + (* TODO: More elaborate warnings etc *) + (* Invalid config. *) + exp) + | _ -> Ast_mapper.default_mapper.expr mapper exp); + } + in + mapper + + let migrate ~entryPointFile ~outputMode = + let path = + match Filename.is_relative entryPointFile with + | true -> Unix.realpath entryPointFile + | false -> entryPointFile + in + let result = + if Filename.check_suffix path ".res" then + let parser = + Res_driver.parsing_engine.parse_implementation ~for_printer:true + in + let {Res_driver.parsetree; comments; source} = parser ~filename:path in + match Cmt.loadCmtInfosFromPath ~path with + | None -> + Error + (Printf.sprintf + "error: failed to run migration for %s because build artifacts \ + could not be found. try to build the project" + path) + | Some {cmt_extra_info = {deprecated_used}} -> + let mapper = makeMapper deprecated_used in + let astMapped = mapper.structure mapper parsetree in + Ok + ( Res_printer.print_implementation + ~width:Res_printer.default_print_width astMapped ~comments, + source ) + else if Filename.check_suffix path ".resi" then + let parser = + Res_driver.parsing_engine.parse_interface ~for_printer:true + in + let {Res_driver.parsetree = signature; comments; source} = + parser ~filename:path + in + let mapper = makeMapper [] in + let astMapped = mapper.signature mapper signature in + Ok + ( Res_printer.print_interface ~width:Res_printer.default_print_width + astMapped ~comments, + source ) + else + Error + (Printf.sprintf + "File extension not supported. This command accepts .res, .resi \ + files") + in + match result with + | Error e -> Error e + | Ok (contents, source) when contents <> source -> ( + match outputMode with + | `Stdout -> Ok contents + | `File -> + let oc = open_out path in + Printf.fprintf oc "%s" contents; + close_out oc; + Ok (Filename.basename path ^ ": File migrated successfully")) + | Ok (contents, _) -> ( + match outputMode with + | `Stdout -> Ok contents + | `File -> Ok (Filename.basename path ^ ": File did not need migration")) +end