Skip to content

Commit a5c0413

Browse files
viratyosinfacebook-github-bot
authored andcommitted
Add command hh --is-subtype <json
Summary: This adds the `--is-subtype` command which allows you to pass JSON via stdin specifying type pairs. A list of results will be returned where each result indicates whether the first type is a subtype of the second type. The first type can be either a position string (similar to `--type-at-pos`) or a json-representation of a type (same format that `--type-at-pos-batch` returns). e.g. ``` {"kind":"pos", "pos":"file:line:col"} ``` or ``` {"kind":"type", "type":TYPE_JSON} ``` The second type must be a json-representation of a type and must be a type that has an environment-independent definition (e.g. no type variables, this, etc). While unbound names are checked for, some lack of type-wellformed-ness is not, e.g. arity of class types with generics. The reason why two positions are not supported is because two positions may have different environments making subtyping a difficult question to answer. If a user is interested in the relationship b/t types at two positions, and one is known to not be environment-dependent, the user can use `--type-at-pos-batch` to get the JSON type of the independent one and then use that with `--is-subtype` and the other position. Reviewed By: vassilmladenov Differential Revision: D38393256 fbshipit-source-id: 55410eeec15845ed438a310b56cd69280cf5e217
1 parent 64ce26d commit a5c0413

14 files changed

+358
-11
lines changed

hphp/hack/src/client/clientArgs.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,9 @@ let parse_check_args cmd =
726726
Arg.String (fun x -> set_mode (MODE_TYPE_ERROR_AT_POS x)),
727727
" (mode) show type error at a given position in file [line:character]"
728728
);
729+
( "--is-subtype",
730+
Arg.Unit (fun () -> set_mode MODE_IS_SUBTYPE),
731+
" (mode) take a JSON list of subtype queries via stdin" );
729732
( "--tast-holes",
730733
Arg.String (fun x -> set_mode (MODE_TAST_HOLES x)),
731734
" (mode) return all TAST Holes in a given file" );

hphp/hack/src/client/clientCheck.ml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,16 @@ let main (args : client_check_env) (local_config : ServerLocalConfig.t) :
512512
in
513513
List.iter responses ~f:print_endline;
514514
Lwt.return (Exit_status.No_error, telemetry)
515+
| MODE_IS_SUBTYPE ->
516+
let stdin = Sys_utils.read_stdin_to_string () in
517+
let%lwt (response, telemetry) = rpc args @@ Rpc.IS_SUBTYPE stdin in
518+
(match response with
519+
| Ok str ->
520+
Printf.printf "%s" str;
521+
Lwt.return (Exit_status.No_error, telemetry)
522+
| Error str ->
523+
Printf.eprintf "%s" str;
524+
raise Exit_status.(Exit_with Input_error))
515525
| MODE_TYPE_ERROR_AT_POS arg ->
516526
let tpos = Str.split (Str.regexp ":") arg in
517527
let (fn, line, char) =

hphp/hack/src/client/clientEnv.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ type client_mode =
7373
| MODE_TYPE_AT_POS of string
7474
| MODE_TYPE_AT_POS_BATCH of string list
7575
| MODE_TYPE_ERROR_AT_POS of string
76+
| MODE_IS_SUBTYPE
7677
| MODE_TAST_HOLES of string
7778
| MODE_FUN_DEPS_AT_POS_BATCH of string list
7879
| MODE_FILE_DEPENDENTS
@@ -174,6 +175,7 @@ let mode_to_string = function
174175
| MODE_TYPE_AT_POS _ -> "MODE_TYPE_AT_POS"
175176
| MODE_TYPE_AT_POS_BATCH _ -> "MODE_TYPE_AT_POS_BATCH"
176177
| MODE_TYPE_ERROR_AT_POS _ -> "MODE_TYPE_ERROR_AT_POS"
178+
| MODE_IS_SUBTYPE -> "MODE_IS_SUBTYPE"
177179
| MODE_TAST_HOLES _ -> "MODE_TAST_HOLES"
178180
| MODE_FUN_DEPS_AT_POS_BATCH _ -> "MODE_FUN_DEPS_AT_POS_BATCH"
179181
| MODE_FILE_DEPENDENTS -> "MODE_FILE_LEVEL_DEPENDENCIES"

hphp/hack/src/server/dune

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,7 @@
467467
serverIdle
468468
serverInferTypeBatch
469469
serverInvalidateUnits
470+
serverIsSubtype
470471
serverLint
471472
serverMethodJumps
472473
serverMethodJumpsBatch

hphp/hack/src/server/serverCommand.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ let rpc_command_needs_full_check : type a. a t -> bool =
6161
| INFER_TYPE _ -> false
6262
| INFER_TYPE_BATCH _ -> false
6363
| INFER_TYPE_ERROR _ -> false
64+
| IS_SUBTYPE _ -> false
6465
| TAST_HOLES _ -> false
6566
| IDE_HOVER _ -> false
6667
| DOCBLOCK_AT _ -> false

hphp/hack/src/server/serverCommandTypes.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ type _ t =
343343
(string * int * int * (int * int) option) list
344344
-> string list t
345345
| INFER_TYPE_ERROR : file_input * int * int -> InferErrorAtPosService.result t
346+
| IS_SUBTYPE : string -> (string, string) result t
346347
| TAST_HOLES : file_input * Tast_hole.filter -> TastHolesService.result t
347348
| IDE_HOVER : string * int * int -> HoverService.result t
348349
| DOCBLOCK_AT :

hphp/hack/src/server/serverCommandTypesUtils.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ let debug_describe_t : type a. a t -> string = function
77
| INFER_TYPE _ -> "INFER_TYPE"
88
| INFER_TYPE_BATCH _ -> "INFER_TYPE_BATCH"
99
| INFER_TYPE_ERROR _ -> "INFER_TYPE_ERROR"
10+
| IS_SUBTYPE _ -> "IS_SUBTYPE"
1011
| TAST_HOLES _ -> "TAST_HOLES"
1112
| IDE_HOVER _ -> "IDE_HOVER"
1213
| DOCBLOCK_AT _ -> "DOCBLOCK_AT"

hphp/hack/src/server/serverInferTypeBatch.ml

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,10 @@ type pos = Relative_path.t * int * int * (int * int) option
1313

1414
type spos = string * int * int * (int * int) option [@@deriving eq, ord]
1515

16-
let recheck_typing ctx (pos_list : pos list) =
16+
let recheck_typing ctx (path_list : Relative_path.t list) =
1717
let files_to_check =
18-
pos_list
19-
|> List.map ~f:(fun (path, _, _, _) -> path)
18+
List.sort path_list ~compare:Relative_path.compare
2019
|> List.remove_consecutive_duplicates ~equal:Relative_path.equal
21-
(* note: our caller has already sorted pos_list *)
2220
in
2321
let (ctx, paths_and_tasts) =
2422
List.fold
@@ -33,6 +31,16 @@ let recheck_typing ctx (pos_list : pos list) =
3331
in
3432
(ctx, paths_and_tasts)
3533

34+
let get_tast_map ctx path_list =
35+
let (ctx, paths_and_tasts) = recheck_typing ctx path_list in
36+
let tasts =
37+
List.fold
38+
paths_and_tasts
39+
~init:Relative_path.Map.empty
40+
~f:(fun map (key, data) -> Relative_path.Map.add map ~key ~data)
41+
in
42+
(ctx, tasts)
43+
3644
let result_to_string result (fn, line, char, range_end) =
3745
Hh_json.(
3846
let obj =
@@ -57,13 +65,8 @@ let result_to_string result (fn, line, char, range_end) =
5765
json_to_string obj)
5866

5967
let helper ctx acc pos_list =
60-
let (ctx, paths_and_tasts) = recheck_typing ctx pos_list in
61-
let tasts =
62-
List.fold
63-
paths_and_tasts
64-
~init:Relative_path.Map.empty
65-
~f:(fun map (key, data) -> Relative_path.Map.add map ~key ~data)
66-
in
68+
let path_list = List.map pos_list ~f:(fun (path, _, _, _) -> path) in
69+
let (ctx, tasts) = get_tast_map ctx path_list in
6770
List.fold pos_list ~init:acc ~f:(fun acc pos ->
6871
let (fn, line, char, range_end) = pos in
6972
let result =

hphp/hack/src/server/serverInferTypeBatch.mli

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@
66
*
77
*)
88

9+
type pos = Relative_path.t * int * int * (int * int) option
10+
11+
val get_tast_map :
12+
Provider_context.t ->
13+
Relative_path.t list ->
14+
Provider_context.t * Tast.program Relative_path.Map.t
15+
916
val go :
1017
MultiWorker.worker list option ->
1118
(string * int * int * (int * int) option) list ->

0 commit comments

Comments
 (0)