Skip to content

Commit

Permalink
Disable redundant type annotation (#1037)
Browse files Browse the repository at this point in the history
* Disable redundant type annotation
* Make it work for coercions too
  • Loading branch information
3Rafal committed Mar 6, 2023
1 parent 1dc8c32 commit a2fe6ff
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 12 deletions.
3 changes: 3 additions & 0 deletions CHANGES.md
Expand Up @@ -3,6 +3,9 @@
## Fixes

- Fix a document syncing issue when utf-16 is the position encoding (#1004)
- Disable "Type-annotate" action for code that is already annotated.
([#1037](https://github.com/ocaml/ocaml-lsp/pull/1037)), fixes
[#1036](https://github.com/ocaml/ocaml-lsp/issues/1036)

# 1.15.1

Expand Down
18 changes: 17 additions & 1 deletion ocaml-lsp-server/src/code_actions/action_type_annotate.ml
Expand Up @@ -7,8 +7,24 @@ let check_typeable_context pipeline pos_start =
let pos_start = Mpipeline.get_lexing_pos pipeline pos_start in
let typer = Mpipeline.typer_result pipeline in
let browse = Mbrowse.of_typedtree (Mtyper.get_typedtree typer) in
let is_exp_constrained = function
| Typedtree.Texp_constraint _, _, _ -> true
| Typedtree.Texp_coerce (Some _, _), _, _ -> true
| _ -> false
in
let is_pat_constrained = function
| Typedtree.Tpat_constraint _, _, _ -> true
| _ -> false
in
let is_valid p extras =
if List.exists ~f:p extras then `Invalid else `Valid
in
match Mbrowse.enclosing pos_start [ browse ] with
| (_, (Expression _ | Pattern _)) :: _ -> `Valid
| (_, Expression e) :: _ -> is_valid is_exp_constrained e.exp_extra
| (_, Pattern { pat_desc = Typedtree.Tpat_any; _ })
:: (_, Pattern { pat_desc = Typedtree.Tpat_alias _; pat_extra; _ })
:: _ -> is_valid is_pat_constrained pat_extra
| (_, Pattern p) :: _ -> is_valid is_pat_constrained p.pat_extra
| _ :: _ | [] -> `Invalid

let get_source_text doc (loc : Loc.t) =
Expand Down
69 changes: 58 additions & 11 deletions ocaml-lsp-server/test/e2e-new/code_actions.ml
Expand Up @@ -47,18 +47,28 @@ let iter_code_actions ?(path = "foo.ml") ~source range k =
Fiber.fork_and_join_unit run_client (fun () ->
run >>> Fiber.Ivar.read diagnostics >>> Client.stop client)

let print_code_actions ?(path = "foo.ml") source range =
let print_code_actions ?(path = "foo.ml") ?(filter = fun _ -> true) source range
=
iter_code_actions ~path ~source range (function
| None -> print_endline "no code actions"
| Some code_actions ->
print_endline "Code actions:";
List.iter code_actions ~f:(fun ca ->
let json =
match ca with
| `Command command -> Command.yojson_of_t command
| `CodeAction ca -> CodeAction.yojson_of_t ca
in
Yojson.Safe.pretty_to_string ~std:false json |> print_endline))
| None -> print_endline "No code actions"
| Some code_actions -> (
code_actions |> List.filter ~f:filter |> function
| [] -> print_endline "No code actions"
| actions ->
print_endline "Code actions:";
List.iter actions ~f:(fun ca ->
let json =
match ca with
| `Command command -> Command.yojson_of_t command
| `CodeAction ca -> CodeAction.yojson_of_t ca
in
Yojson.Safe.pretty_to_string ~std:false json |> print_endline)))
let find_annotate_action =
let open CodeAction in
function
| `CodeAction { kind = Some (Other "type-annotate"); _ } -> true
| _ -> false
let%expect_test "code actions" =
let source = {ocaml|
Expand Down Expand Up @@ -106,3 +116,40 @@ let foo = 123
"kind": "switch",
"title": "Create foo.mli"
} |}]
let%expect_test "does not type-annotate already annotated argument" =
let source = {ocaml|
let f (x : int) = 1
|ocaml} in
let range =
let start = Position.create ~line:1 ~character:7 in
let end_ = Position.create ~line:1 ~character:8 in
Range.create ~start ~end_
in
print_code_actions source range ~filter:find_annotate_action;
[%expect {| No code actions |}]
let%expect_test "does not type-annotate already annotated expression" =
let source = {ocaml|
let f x = (1 : int)
|ocaml} in
let range =
let start = Position.create ~line:1 ~character:11 in
let end_ = Position.create ~line:1 ~character:12 in
Range.create ~start ~end_
in
print_code_actions source range ~filter:find_annotate_action;
[%expect {| No code actions |}]
let%expect_test "does not type-annotate already annotated and coerced \
expression" =
let source = {ocaml|
let f x = (1 : int :> int)
|ocaml} in
let range =
let start = Position.create ~line:1 ~character:11 in
let end_ = Position.create ~line:1 ~character:12 in
Range.create ~start ~end_
in
print_code_actions source range ~filter:find_annotate_action;
[%expect {| No code actions |}]

0 comments on commit a2fe6ff

Please sign in to comment.