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 40 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
97bb125
base setup for actions + tests
zth Jul 26, 2025
4c78cf4
implement the actual rewriting
zth Jul 26, 2025
647117b
map
zth Jul 26, 2025
079efb0
add and remove await
zth Jul 26, 2025
bbaaa43
rewrite object to record
zth Jul 26, 2025
3f96d51
rewrite array to tuple
zth Jul 26, 2025
94a5fab
more array to tuple
zth Jul 26, 2025
bb31a5f
jsx conversions
zth Jul 26, 2025
00846d7
comments + rewrite ident
zth Jul 26, 2025
83a8667
more todo comments for actions that could be useful
zth Jul 27, 2025
22de783
format
zth Jul 27, 2025
d8ee98e
more todo comments
zth Jul 27, 2025
fe9513c
refactor to centralize generating actions from warnings
zth Jul 27, 2025
1e4b7c4
move remaining warning driven actions to centralized place
zth Jul 27, 2025
a8bcbff
add value_bindings to Ast_mapper
zth Jul 27, 2025
9934bce
prefix unused
zth Jul 27, 2025
c596299
add value_bindings to Ast_iterator as well
zth Jul 27, 2025
d85b4d0
format
zth Jul 27, 2025
c2c6aae
spellcheck
zth Jul 28, 2025
e8558ce
allow filtering actions, and add test for removing unused var entirely
zth Jul 28, 2025
f4d7c8a
emit all available actions in a comment in applied file
zth Jul 28, 2025
ef78139
fix ident-to-module action
zth Jul 28, 2025
4ccbb56
unused value declarations
zth Jul 28, 2025
73ac801
remove unused modules and types
zth Jul 28, 2025
f020c60
remove unused rec flag
zth Jul 28, 2025
8ba0b91
format
zth Jul 28, 2025
15b37ae
force open
zth Jul 28, 2025
fe165b8
cleanup
zth Jul 28, 2025
ed90c64
remove record spread
zth Jul 28, 2025
603b066
remove irrelevant
zth Jul 28, 2025
cdb57c5
handle top level
zth Jul 28, 2025
a0c3724
clenaup
zth Jul 28, 2025
3e56f63
emit all available actions into applied file, not just the filtered ones
zth Jul 28, 2025
9c27553
make optional arg labelled
zth Jul 28, 2025
8986037
labelled to optional arg
zth Jul 28, 2025
884a7da
partially apply function
zth Jul 28, 2025
ee9710d
add missing args
zth Jul 28, 2025
c4cf0e6
pass record field expr as optional
zth Jul 28, 2025
69ccd83
add action for automatically unwrapping record field access through o…
zth Jul 29, 2025
2a5d637
add test files
zth Jul 29, 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