Skip to content

Commit efe0489

Browse files
committed
spellcheck
1 parent 58b8a78 commit efe0489

File tree

4 files changed

+40
-13
lines changed

4 files changed

+40
-13
lines changed

compiler/ml/typetexp.ml

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ type error =
4141
| Cannot_quantify of string * type_expr
4242
| Multiple_constraints_on_type of Longident.t
4343
| Method_mismatch of string * type_expr * type_expr
44-
| Unbound_value of Longident.t
44+
| Unbound_value of Longident.t * Location.t
4545
| Unbound_constructor of Longident.t
4646
| Unbound_label of Longident.t * type_expr option
4747
| Unbound_module of Longident.t
@@ -134,7 +134,9 @@ let find_all_labels =
134134
let find_value env loc lid =
135135
Env.check_value_name (Longident.last lid) loc;
136136
let ((path, decl) as r) =
137-
find_component Env.lookup_value (fun lid -> Unbound_value lid) env loc lid
137+
find_component Env.lookup_value
138+
(fun lid -> Unbound_value (lid, loc))
139+
env loc lid
138140
in
139141
Builtin_attributes.check_deprecated loc decl.val_attributes (Path.name path);
140142
r
@@ -720,29 +722,29 @@ let transl_type_scheme env styp =
720722
open Format
721723
open Printtyp
722724

723-
let did_you_mean ppf choices : bool =
725+
let did_you_mean ppf choices : bool * string list =
724726
(* flush now to get the error report early, in the (unheard of) case
725727
where the linear search would take a bit of time; in the worst
726728
case, the user has seen the error, she can interrupt the process
727729
before the spell-checking terminates. *)
728730
Format.fprintf ppf "@?";
729731
match choices () with
730-
| [] -> false
731-
| last :: rev_rest ->
732+
| [] -> (false, [])
733+
| last :: rev_rest as choices ->
732734
(* TODO(actions) Rewrite ident *)
733735
Format.fprintf ppf "@[<v 2>@,@,@{<info>Hint: Did you mean %s%s%s?@}@]"
734736
(String.concat ", " (List.rev rev_rest))
735737
(if rev_rest = [] then "" else " or ")
736738
last;
737-
true
739+
(true, choices)
738740

739741
let super_spellcheck ppf fold env lid =
740742
let choices path name : string list =
741743
let env : string list = fold (fun x _ _ xs -> x :: xs) path env [] in
742744
Misc.spellcheck env name
743745
in
744746
match lid with
745-
| Longident.Lapply _ -> false
747+
| Longident.Lapply _ -> (false, [])
746748
| Longident.Lident s -> did_you_mean ppf (fun _ -> choices None s)
747749
| Longident.Ldot (r, s) -> did_you_mean ppf (fun _ -> choices (Some r) s)
748750

@@ -774,7 +776,7 @@ let report_error env ppf = function
774776
(* modified *)
775777
Format.fprintf ppf "@[<v>This type constructor, `%a`, can't be found.@ "
776778
Printtyp.longident lid;
777-
let has_candidate = super_spellcheck ppf Env.fold_types env lid in
779+
let has_candidate, _ = super_spellcheck ppf Env.fold_types env lid in
778780
if not has_candidate then
779781
(* TODO(actions) Add rec flag *)
780782
Format.fprintf ppf
@@ -846,7 +848,7 @@ let report_error env ppf = function
846848
Printtyp.reset_and_mark_loops_list [ty; ty'];
847849
fprintf ppf "@[<hov>Method '%s' has type %a,@ which should be %a@]" l
848850
Printtyp.type_expr ty Printtyp.type_expr ty')
849-
| Unbound_value lid -> (
851+
| Unbound_value (lid, loc) -> (
850852
(* modified *)
851853
(match lid with
852854
| Ldot (outer, inner) ->
@@ -855,12 +857,22 @@ let report_error env ppf = function
855857
| other_ident ->
856858
Format.fprintf ppf "The value %a can't be found" Printtyp.longident
857859
other_ident);
858-
let did_spellcheck = super_spellcheck ppf Env.fold_values env lid in
860+
let did_spellcheck, choices =
861+
super_spellcheck ppf Env.fold_values env lid
862+
in
863+
if did_spellcheck then
864+
choices
865+
|> List.iter (fun choice ->
866+
Cmt_utils.add_possible_action
867+
{
868+
loc;
869+
action = Cmt_utils.RewriteIdent {new_ident = Lident choice};
870+
description = "Change to `" ^ choice ^ "`";
871+
});
859872
(* For cases such as when the user refers to something that's a value with
860873
a lowercase identifier in JS but a module in ReScript.
861874
862875
'Console' is a typical example, where JS is `console.log` and ReScript is `Console.log`. *)
863-
(* TODO(codemods) Add codemod for refering to the module instead. *)
864876
let as_module =
865877
match lid with
866878
| Lident name -> (
@@ -875,7 +887,18 @@ let report_error env ppf = function
875887
match as_module with
876888
| None -> ()
877889
| Some module_path ->
878-
(* TODO(actions) Rewrite ident *)
890+
let new_ident =
891+
module_path |> Printtyp.string_of_path |> Longident.parse
892+
in
893+
Cmt_utils.add_possible_action
894+
{
895+
loc;
896+
action = Cmt_utils.RewriteIdent {new_ident};
897+
description =
898+
"Change to `"
899+
^ (new_ident |> Longident.flatten |> String.concat ".")
900+
^ "`";
901+
};
879902
Format.fprintf ppf "@,@[<v 2>@,@[%s to use the module @{<info>%a@}?@]@]"
880903
(if did_spellcheck then "Or did you mean" else "Maybe you meant")
881904
Printtyp.path module_path)

compiler/ml/typetexp.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ type error =
5050
| Cannot_quantify of string * type_expr
5151
| Multiple_constraints_on_type of Longident.t
5252
| Method_mismatch of string * type_expr * type_expr
53-
| Unbound_value of Longident.t
53+
| Unbound_value of Longident.t * Location.t
5454
| Unbound_constructor of Longident.t
5555
| Unbound_label of Longident.t * type_expr option
5656
| Unbound_module of Longident.t
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
let aaaaa = 10
2+
let b = aaaaa
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
let aaaaa = 10
2+
let b = aaaab

0 commit comments

Comments
 (0)