Skip to content

Commit 5b6c35d

Browse files
committed
Introduce initial type hints in playground bundle results
1 parent f6e0629 commit 5b6c35d

File tree

3 files changed

+102
-55
lines changed

3 files changed

+102
-55
lines changed

jscomp/main/jsoo_common.ml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ module Js = struct
1414
type obj
1515
external obj : (string * any) array -> obj = "caml_js_object"
1616
end
17+
1718
type (-'a, +'b) meth_callback
1819
type 'a callback = (unit, 'a) meth_callback
1920

@@ -28,6 +29,7 @@ module Js = struct
2829

2930
type 'a js_array
3031
external array : 'a array -> 'a js_array = "caml_js_from_array"
32+
external to_array : 'a js_array t -> 'a array = "caml_js_to_array"
3133

3234
external bool : bool -> bool t = "caml_js_from_bool"
3335
external to_bool : bool t -> bool = "caml_js_to_bool"
@@ -38,6 +40,12 @@ module Js = struct
3840

3941
external create_file : js_string t -> js_string t -> unit = "caml_create_file"
4042
external to_bytestring : js_string t -> string = "caml_js_to_byte_string"
43+
44+
type 'a opt = 'a
45+
type 'a optdef = 'a
46+
47+
let null : 'a opt = Unsafe.pure_js_expr "null"
48+
external some : 'a -> 'a opt = "%identity"
4149
end
4250

4351
module Sys_js = struct

jscomp/main/jsoo_common.mli

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ module Js :
3232

3333
type 'a js_array
3434
external array : 'a array -> 'a js_array = "caml_js_from_array"
35+
external to_array : 'a js_array t -> 'a array = "caml_js_to_array"
3536

3637
external bool : bool -> bool t = "caml_js_from_bool"
3738
external to_bool : bool t -> bool = "caml_js_to_bool"
@@ -44,6 +45,11 @@ module Js :
4445
= "caml_create_file"
4546
external to_bytestring : js_string t -> string = "caml_js_to_byte_string"
4647

48+
type 'a opt = 'a
49+
type 'a optdef = 'a
50+
val null : 'a opt
51+
val some : 'a -> 'a opt
52+
(** Consider a value into a possibly null value. *)
4753
end
4854

4955
module Sys_js :

jscomp/refmt/jsoo_refmt_main.ml

Lines changed: 88 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ This is usually the file you want to build for the full playground experience.
4848
* This will allow the frontend to have different sets of the same bindings,
4949
* and use the proper interfaces as stated by the apiVersion.
5050
* *)
51-
let apiVersion = "1.0"
51+
let apiVersion = "1.1"
5252

5353
module Js = Jsoo_common.Js
5454
module Sys_js = Jsoo_common.Sys_js
@@ -360,6 +360,21 @@ let rescript_parse ~filename src =
360360
in
361361
structure
362362

363+
364+
module Printer = struct
365+
let printExpr typ =
366+
Printtyp.reset_names();
367+
Res_doc.toString
368+
~width:60 (Res_outcome_printer.printOutTypeDoc (Printtyp.tree_of_typexp false typ))
369+
370+
371+
let printDecl ~recStatus name decl =
372+
Printtyp.reset_names();
373+
Res_doc.toString
374+
~width:60
375+
(Res_outcome_printer.printOutSigItemDoc (Printtyp.tree_of_type_declaration (Ident.create name) decl recStatus))
376+
end
377+
363378
module Compile = struct
364379
(* Apparently it's not possible to retrieve the loc info from
365380
* Location.error_of_exn properly, so we need to do some extra
@@ -448,6 +463,76 @@ module Compile = struct
448463
Warnings.reset_fatal ();
449464
Env.reset_cache_toplevel ()
450465

466+
(* Collects the type information from the typed_tree, so we can use that
467+
* data to display types on hover etc.
468+
*
469+
* Note: start / end positions
470+
* *)
471+
let collectTypeHints typed_tree =
472+
let open Typedtree in
473+
let createTypeHintObj loc kind hint =
474+
let open Lexing in
475+
let open Location in
476+
let (_ , startline, startcol) = Location.get_pos_info loc.loc_start in
477+
let (_ , endline, endcol) = Location.get_pos_info loc.loc_end in
478+
Js.Unsafe.(obj [|
479+
"start", inject @@ (obj [|
480+
"line", inject @@ (startline |> float_of_int |> Js.number_of_float);
481+
"col", inject @@ (startcol|> float_of_int |> Js.number_of_float);
482+
|]);
483+
"end", inject @@ (obj [|
484+
"line", inject @@ (endline |> float_of_int |> Js.number_of_float);
485+
"col", inject @@ (endcol |> float_of_int |> Js.number_of_float);
486+
|]);
487+
"kind", inject @@ Js.string kind;
488+
"hint", inject @@ Js.string hint;
489+
|])
490+
in
491+
let (structure, _) = typed_tree in
492+
let acc = ref [] in
493+
let module Iter = TypedtreeIter.MakeIterator (struct
494+
include TypedtreeIter.DefaultIteratorArgument
495+
496+
let cur_rec_status = ref None
497+
498+
let enter_expression expr =
499+
let hint = Printer.printExpr expr.exp_type in
500+
let obj = createTypeHintObj expr.exp_loc "expression" hint in
501+
acc := obj :: !acc
502+
503+
let enter_binding binding =
504+
let hint = Printer.printExpr binding.vb_expr.exp_type in
505+
let obj = createTypeHintObj binding.vb_loc "binding" hint in
506+
acc := obj :: !acc
507+
508+
let enter_core_type ct =
509+
let hint = Printer.printExpr ct.ctyp_type in
510+
let obj = createTypeHintObj ct.ctyp_loc "core_type" hint in
511+
acc := obj :: !acc
512+
513+
let enter_type_declarations recFlag =
514+
let status = match recFlag with
515+
| Asttypes.Nonrecursive -> Types.Trec_not
516+
| Recursive -> Trec_first
517+
in
518+
cur_rec_status := Some status
519+
520+
let enter_type_declaration tdecl =
521+
let open Types in
522+
match !cur_rec_status with
523+
| Some recStatus ->
524+
let hint = Printer.printDecl ~recStatus tdecl.typ_name.Asttypes.txt tdecl.typ_type in
525+
let obj = createTypeHintObj tdecl.typ_loc "type_declaration" hint in
526+
acc := obj :: !acc;
527+
(match recStatus with
528+
| Trec_not
529+
| Trec_first -> cur_rec_status := Some Trec_next
530+
| _ -> ())
531+
| None -> ()
532+
end)
533+
in
534+
List.iter Iter.iter_structure_item structure.str_items;
535+
Js.array (!acc |> Array.of_list)
451536

452537
let implementation ~(config: BundleConfig.t) ~lang str : Js.Unsafe.obj =
453538
let {BundleConfig.module_system; warn_flags} = config in
@@ -488,6 +573,7 @@ module Compile = struct
488573
lam)
489574
(Ext_pp.from_buffer buffer) in
490575
let v = Buffer.contents buffer in
576+
let typeHints = collectTypeHints typed_tree in
491577
Js.Unsafe.(obj [|
492578
"js_code", inject @@ Js.string v;
493579
"warnings",
@@ -497,6 +583,7 @@ module Compile = struct
497583
|> Js.array
498584
|> inject
499585
);
586+
"type_hints", inject @@ typeHints;
500587
"type" , inject @@ Js.string "success"
501588
|]))
502589
with
@@ -651,60 +738,6 @@ module Export = struct
651738
in
652739
obj attrs
653740

654-
let make_config_attrs ~(config: BundleConfig.t) =
655-
let open Lang in
656-
let set_module_system value =
657-
match value with
658-
| "es6" ->
659-
config.module_system <- Js_packages_info.Es6; true
660-
| "nodejs" ->
661-
config.module_system <- NodeJS; true
662-
| _ -> false in
663-
let set_filename value =
664-
config.filename <- Some value; true
665-
in
666-
let set_warn_flags value =
667-
config.warn_flags <- value; true
668-
in
669-
Js.Unsafe.(
670-
[|
671-
"setModuleSystem",
672-
inject @@
673-
Js.wrap_meth_callback
674-
(fun _ value ->
675-
(Js.bool (set_module_system (Js.to_string value)))
676-
);
677-
"setFilename",
678-
inject @@
679-
Js.wrap_meth_callback
680-
(fun _ value ->
681-
(Js.bool (set_filename (Js.to_string value)))
682-
);
683-
"setWarnFlags",
684-
inject @@
685-
Js.wrap_meth_callback
686-
(fun _ value ->
687-
(Js.bool (set_warn_flags (Js.to_string value)))
688-
);
689-
"list",
690-
inject @@
691-
Js.wrap_meth_callback
692-
(fun _ ->
693-
(Js.Unsafe.(obj
694-
[|
695-
"module_system",
696-
inject @@ (
697-
config.module_system
698-
|> BundleConfig.string_of_module_system
699-
|> Js.string
700-
);
701-
"warn_flags",
702-
inject @@ (Js.string config.warn_flags);
703-
|]))
704-
);
705-
706-
|])
707-
708741
(* Creates a "compiler instance" binding the configuration context to the specific compile / formatter functions *)
709742
let make () =
710743
let open Lang in

0 commit comments

Comments
 (0)