Skip to content

[WIP] Actions #7726

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 38 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
fd096d4
base setup for actions + tests
zth Jul 26, 2025
79416ff
implement the actual rewriting
zth Jul 26, 2025
3f14a64
map
zth Jul 26, 2025
90214ee
add and remove await
zth Jul 26, 2025
b15e919
rewrite object to record
zth Jul 26, 2025
9ce303a
rewrite array to tuple
zth Jul 26, 2025
2a4242f
more array to tuple
zth Jul 26, 2025
46f4dad
jsx conversions
zth Jul 26, 2025
dfdd698
comments + rewrite ident
zth Jul 26, 2025
e501463
more todo comments for actions that could be useful
zth Jul 27, 2025
ad14302
format
zth Jul 27, 2025
7505c46
more todo comments
zth Jul 27, 2025
d429cd8
refactor to centralize generating actions from warnings
zth Jul 27, 2025
869c4e7
move remaining warning driven actions to centralized place
zth Jul 27, 2025
1991bf0
add value_bindings to Ast_mapper
zth Jul 27, 2025
5abe1a5
prefix unused
zth Jul 27, 2025
7d6ed7d
add value_bindings to Ast_iterator as well
zth Jul 27, 2025
7ef247d
format
zth Jul 27, 2025
d7b9c69
spellcheck
zth Jul 28, 2025
3ed02fe
allow filtering actions, and add test for removing unused var entirely
zth Jul 28, 2025
0d15c59
emit all available actions in a comment in applied file
zth Jul 28, 2025
d129379
fix ident-to-module action
zth Jul 28, 2025
5d48bd3
unused value declarations
zth Jul 28, 2025
870d0b5
remove unused modules and types
zth Jul 28, 2025
3ca2a95
remove unused rec flag
zth Jul 28, 2025
2bf35c3
format
zth Jul 28, 2025
6c48823
force open
zth Jul 28, 2025
50149c8
cleanup
zth Jul 28, 2025
3cb3c7f
remove record spread
zth Jul 28, 2025
3ca1f7d
remove irrelevant
zth Jul 28, 2025
30473fe
handle top level
zth Jul 28, 2025
ae9eda4
clenaup
zth Jul 28, 2025
1383616
emit all available actions into applied file, not just the filtered ones
zth Jul 28, 2025
44984d5
make optional arg labelled
zth Jul 28, 2025
b93f666
labelled to optional arg
zth Jul 28, 2025
f78269f
partially apply function
zth Jul 28, 2025
4dfa741
add missing args
zth Jul 28, 2025
16694f6
pass record field expr as optional
zth Jul 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions analysis/src/Cmt.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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)
2 changes: 2 additions & 0 deletions compiler/bsc/rescript_compiler_main.ml
Original file line number Diff line number Diff line change
Expand Up @@ -462,4 +462,6 @@ let _ : unit =
exit 2
| x ->
Location.report_exception ppf x;
(* Re-save cmt so we can get the possible actions *)
Cmt_format.resave_cmt_with_possible_actions ();
exit 2
7 changes: 6 additions & 1 deletion compiler/ext/warnings.ml
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,9 @@ let message = function
| Ambiguous_name (_slist, tl, true) ->
"these field labels belong to several types: " ^ String.concat " " tl
^ "\nThe first one was selected. Please disambiguate if this is wrong."
| Nonoptional_label s -> "the label " ^ s ^ " is not optional."
| Nonoptional_label s ->
(* TODO(actions) When does this happen? *)
"the label " ^ s ^ " is not optional."
| Open_shadow_identifier (kind, s) ->
Printf.sprintf
"this open statement shadows the %s identifier %s (which is later used)"
Expand Down Expand Up @@ -682,3 +684,6 @@ let loc_to_string (loc : loc) : string =
(loc.loc_start.pos_cnum - loc.loc_start.pos_bol)
loc.loc_end.pos_lnum
(loc.loc_end.pos_cnum - loc.loc_end.pos_bol)

let emit_possible_actions_from_warning : (loc -> t -> unit) ref =
ref (fun _ _ -> ())
2 changes: 2 additions & 0 deletions compiler/ext/warnings.mli
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,5 @@ val loc_to_string : loc -> string
(**
Turn the location into a string with (line,column--line,column) format.
*)

val emit_possible_actions_from_warning : (loc -> t -> unit) ref
29 changes: 16 additions & 13 deletions compiler/ml/ast_iterator.ml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ type iterator = {
open_description: iterator -> open_description -> unit;
pat: iterator -> pattern -> unit;
payload: iterator -> payload -> unit;
record_field: iterator -> expression record_element -> unit;
record_field_pat: iterator -> pattern record_element -> unit;
signature: iterator -> signature -> unit;
signature_item: iterator -> signature_item -> unit;
structure: iterator -> structure -> unit;
Expand All @@ -53,6 +55,7 @@ type iterator = {
type_extension: iterator -> type_extension -> unit;
type_kind: iterator -> type_kind -> unit;
value_binding: iterator -> value_binding -> unit;
value_bindings: iterator -> value_binding list -> unit;
value_description: iterator -> value_description -> unit;
with_constraint: iterator -> with_constraint -> unit;
}
Expand Down Expand Up @@ -250,7 +253,7 @@ module M = struct
| Pstr_eval (x, attrs) ->
sub.expr sub x;
sub.attributes sub attrs
| Pstr_value (_r, vbs) -> List.iter (sub.value_binding sub) vbs
| Pstr_value (_r, vbs) -> sub.value_bindings sub vbs
| Pstr_primitive vd -> sub.value_description sub vd
| Pstr_type (_rf, l) -> List.iter (sub.type_declaration sub) l
| Pstr_typext te -> sub.type_extension sub te
Expand Down Expand Up @@ -289,7 +292,7 @@ module E = struct
| Pexp_ident x -> iter_loc sub x
| Pexp_constant _ -> ()
| Pexp_let (_r, vbs, e) ->
List.iter (sub.value_binding sub) vbs;
sub.value_bindings sub vbs;
sub.expr sub e
| Pexp_fun {default = def; lhs = p; rhs = e} ->
iter_opt (sub.expr sub) def;
Expand All @@ -310,11 +313,7 @@ module E = struct
iter_opt (sub.expr sub) arg
| Pexp_variant (_lab, eo) -> iter_opt (sub.expr sub) eo
| Pexp_record (l, eo) ->
List.iter
(fun {lid; x = exp} ->
iter_loc sub lid;
sub.expr sub exp)
l;
List.iter (sub.record_field sub) l;
iter_opt (sub.expr sub) eo
| Pexp_field (e, lid) ->
sub.expr sub e;
Expand Down Expand Up @@ -400,12 +399,7 @@ module P = struct
iter_loc sub l;
iter_opt (sub.pat sub) p
| Ppat_variant (_l, p) -> iter_opt (sub.pat sub) p
| Ppat_record (lpl, _cf) ->
List.iter
(fun {lid; x = pat} ->
iter_loc sub lid;
sub.pat sub pat)
lpl
| Ppat_record (lpl, _cf) -> List.iter (sub.record_field_pat sub) lpl
| Ppat_array pl -> List.iter (sub.pat sub) pl
| Ppat_or (p1, p2) ->
sub.pat sub p1;
Expand Down Expand Up @@ -489,6 +483,7 @@ let default_iterator =
this.expr this pvb_expr;
this.location this pvb_loc;
this.attributes this pvb_attributes);
value_bindings = (fun this l -> List.iter (this.value_binding this) l);
constructor_declaration =
(fun this {pcd_name; pcd_args; pcd_res; pcd_loc; pcd_attributes} ->
iter_loc this pcd_name;
Expand Down Expand Up @@ -528,4 +523,12 @@ let default_iterator =
| PPat (x, g) ->
this.pat this x;
iter_opt (this.expr this) g);
record_field =
(fun this {lid; x; opt = _} ->
iter_loc this lid;
this.expr this x);
record_field_pat =
(fun this {lid; x; opt = _} ->
iter_loc this lid;
this.pat this x);
}
3 changes: 3 additions & 0 deletions compiler/ml/ast_iterator.mli
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ type iterator = {
open_description: iterator -> open_description -> unit;
pat: iterator -> pattern -> unit;
payload: iterator -> payload -> unit;
record_field: iterator -> expression record_element -> unit;
record_field_pat: iterator -> pattern record_element -> unit;
signature: iterator -> signature -> unit;
signature_item: iterator -> signature_item -> unit;
structure: iterator -> structure -> unit;
Expand All @@ -51,6 +53,7 @@ type iterator = {
type_extension: iterator -> type_extension -> unit;
type_kind: iterator -> type_kind -> unit;
value_binding: iterator -> value_binding -> unit;
value_bindings: iterator -> value_binding list -> unit;
value_description: iterator -> value_description -> unit;
with_constraint: iterator -> with_constraint -> unit;
}
Expand Down
27 changes: 15 additions & 12 deletions compiler/ml/ast_mapper.ml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ type mapper = {
open_description: mapper -> open_description -> open_description;
pat: mapper -> pattern -> pattern;
payload: mapper -> payload -> payload;
record_field:
mapper -> expression record_element -> expression record_element;
record_field_pat: mapper -> pattern record_element -> pattern record_element;
signature: mapper -> signature -> signature;
signature_item: mapper -> signature_item -> signature_item;
structure: mapper -> structure -> structure;
Expand All @@ -57,6 +60,7 @@ type mapper = {
type_extension: mapper -> type_extension -> type_extension;
type_kind: mapper -> type_kind -> type_kind;
value_binding: mapper -> value_binding -> value_binding;
value_bindings: mapper -> value_binding list -> value_binding list;
value_description: mapper -> value_description -> value_description;
with_constraint: mapper -> with_constraint -> with_constraint;
}
Expand Down Expand Up @@ -247,7 +251,7 @@ module M = struct
match desc with
| Pstr_eval (x, attrs) ->
eval ~loc ~attrs:(sub.attributes sub attrs) (sub.expr sub x)
| Pstr_value (r, vbs) -> value ~loc r (List.map (sub.value_binding sub) vbs)
| Pstr_value (r, vbs) -> value ~loc r (sub.value_bindings sub vbs)
| Pstr_primitive vd -> primitive ~loc (sub.value_description sub vd)
| Pstr_type (rf, l) -> type_ ~loc rf (List.map (sub.type_declaration sub) l)
| Pstr_typext te -> type_extension ~loc (sub.type_extension sub te)
Expand Down Expand Up @@ -287,7 +291,7 @@ module E = struct
| Pexp_ident x -> ident ~loc ~attrs (map_loc sub x)
| Pexp_constant x -> constant ~loc ~attrs x
| Pexp_let (r, vbs, e) ->
let_ ~loc ~attrs r (List.map (sub.value_binding sub) vbs) (sub.expr sub e)
let_ ~loc ~attrs r (sub.value_bindings sub vbs) (sub.expr sub e)
| Pexp_fun {arg_label = lab; default = def; lhs = p; rhs = e; arity; async}
->
fun_ ~loc ~attrs ~arity ~async lab
Expand All @@ -306,10 +310,7 @@ module E = struct
variant ~loc ~attrs lab (map_opt (sub.expr sub) eo)
| Pexp_record (l, eo) ->
record ~loc ~attrs
(List.map
(fun {lid; x = exp; opt} ->
{lid = map_loc sub lid; x = sub.expr sub exp; opt})
l)
(List.map (sub.record_field sub) l)
(map_opt (sub.expr sub) eo)
| Pexp_field (e, lid) ->
field ~loc ~attrs (sub.expr sub e) (map_loc sub lid)
Expand Down Expand Up @@ -392,12 +393,7 @@ module P = struct
construct ~loc ~attrs (map_loc sub l) (map_opt (sub.pat sub) p)
| Ppat_variant (l, p) -> variant ~loc ~attrs l (map_opt (sub.pat sub) p)
| Ppat_record (lpl, cf) ->
record ~loc ~attrs
(List.map
(fun {lid; x = pat; opt} ->
{lid = map_loc sub lid; x = sub.pat sub pat; opt})
lpl)
cf
record ~loc ~attrs (List.map (sub.record_field_pat sub) lpl) cf
| Ppat_array pl -> array ~loc ~attrs (List.map (sub.pat sub) pl)
| Ppat_or (p1, p2) -> or_ ~loc ~attrs (sub.pat sub p1) (sub.pat sub p2)
| Ppat_constraint (p, t) ->
Expand Down Expand Up @@ -475,6 +471,7 @@ let default_mapper =
Vb.mk (this.pat this pvb_pat) (this.expr this pvb_expr)
~loc:(this.location this pvb_loc)
~attrs:(this.attributes this pvb_attributes));
value_bindings = (fun this l -> List.map (this.value_binding this) l);
constructor_declaration =
(fun this {pcd_name; pcd_args; pcd_res; pcd_loc; pcd_attributes} ->
Type.constructor (map_loc this pcd_name)
Expand Down Expand Up @@ -509,6 +506,12 @@ let default_mapper =
| PSig x -> PSig (this.signature this x)
| PTyp x -> PTyp (this.typ this x)
| PPat (x, g) -> PPat (this.pat this x, map_opt (this.expr this) g));
record_field =
(fun this {lid; x; opt} ->
{lid = map_loc this lid; x = this.expr this x; opt});
record_field_pat =
(fun this {lid; x; opt} ->
{lid = map_loc this lid; x = this.pat this x; opt});
}

let rec extension_of_error {loc; msg; if_highlight; sub} =
Expand Down
4 changes: 4 additions & 0 deletions compiler/ml/ast_mapper.mli
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ type mapper = {
open_description: mapper -> open_description -> open_description;
pat: mapper -> pattern -> pattern;
payload: mapper -> payload -> payload;
record_field:
mapper -> expression record_element -> expression record_element;
record_field_pat: mapper -> pattern record_element -> pattern record_element;
signature: mapper -> signature -> signature;
signature_item: mapper -> signature_item -> signature_item;
structure: mapper -> structure -> structure;
Expand All @@ -85,6 +88,7 @@ type mapper = {
type_extension: mapper -> type_extension -> type_extension;
type_kind: mapper -> type_kind -> type_kind;
value_binding: mapper -> value_binding -> value_binding;
value_bindings: mapper -> value_binding list -> value_binding list;
value_description: mapper -> value_description -> value_description;
with_constraint: mapper -> with_constraint -> with_constraint;
}
Expand Down
33 changes: 32 additions & 1 deletion compiler/ml/cmt_format.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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_possible_actions : Cmt_utils.cmt_action list;
}

type error =
Expand Down Expand Up @@ -154,15 +155,22 @@ let read_cmi filename =

let saved_types = ref []
let value_deps = ref []
let possible_actions = ref []

let clear () =
saved_types := [];
value_deps := []
value_deps := [];
possible_actions := []

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 add_possible_action action =
possible_actions := action :: !possible_actions

let _ = Cmt_utils._add_possible_action := add_possible_action

let record_value_dependency vd1 vd2 =
if vd1.Types.val_loc <> vd2.Types.val_loc then
value_deps := (vd1, vd2) :: !value_deps
Expand All @@ -172,8 +180,30 @@ let save_cmt _filename _modname _binary_annots _sourcefile _initial_env _cmi = (
#else
open Cmi_format

let current_cmt_filename = ref None

(* TODO: Terrible hack. Figure out way to do this without saving the cmt file twice.
Probably change how/where we save the cmt, and delay it to after writing errors, if possible.
*)
let resave_cmt_with_possible_actions () =
if List.length !possible_actions > 0 then begin
match !current_cmt_filename with
| None -> ()
| Some filename ->
let current_cmt = read_cmt filename in
Misc.output_to_bin_file_directly filename
(fun _temp_file_name oc ->
let cmt = {
current_cmt with
cmt_possible_actions = current_cmt.cmt_possible_actions @ !possible_actions;
} in
output_cmt oc cmt)
end;
clear ()

let save_cmt filename modname binary_annots sourcefile initial_env cmi =
if !Clflags.binary_annotations then begin
current_cmt_filename := Some filename;
Misc.output_to_bin_file_directly filename
(fun temp_file_name oc ->
let this_crc =
Expand All @@ -197,6 +227,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_possible_actions = !possible_actions;
} in
output_cmt oc cmt)
end;
Expand Down
3 changes: 3 additions & 0 deletions compiler/ml/cmt_format.mli
Original file line number Diff line number Diff line change
Expand Up @@ -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_possible_actions: Cmt_utils.cmt_action list;
}

type error = Not_a_typedtree of string
Expand Down Expand Up @@ -111,6 +112,8 @@ val set_saved_types : binary_part list -> unit
val record_value_dependency :
Types.value_description -> Types.value_description -> unit

val resave_cmt_with_possible_actions : unit -> unit

(*

val is_magic_number : string -> bool
Expand Down
Loading
Loading