Skip to content

Commit 45b1a20

Browse files
Developer playground: genType support and sourcemap scaffolding
1 parent 912e189 commit 45b1a20

8 files changed

Lines changed: 400 additions & 13 deletions

File tree

compiler/jsoo/dune

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@
77
(= %{profile} browser))
88
(flags
99
(:standard -w +a-4-9-40-42-44-45))
10-
(libraries core syntax ml js_of_ocaml))
10+
(libraries core syntax ml gentype js_of_ocaml))

compiler/jsoo/jsoo_playground_main.ml

Lines changed: 102 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,9 @@
5252
* v5: Removed .ml support.
5353
* v6: Added `config.experimental_features` and `config.jsx_preserve_mode` to the BundleConfig.
5454
* v7: Added debug dump output APIs for developer playground tooling.
55+
* v8: Added gentype debug output for developer playground tooling.
5556
* *)
56-
let api_version = "7"
57+
let api_version = "8"
5758

5859
module Js = Js_of_ocaml.Js
5960

@@ -78,6 +79,7 @@ module BundleConfig = struct
7879
mutable open_modules: string list;
7980
mutable experimental_features: string list;
8081
mutable jsx_preserve_mode: bool;
82+
mutable gentype_enabled: bool;
8183
}
8284

8385
let make () =
@@ -88,6 +90,7 @@ module BundleConfig = struct
8890
open_modules = [];
8991
experimental_features = [];
9092
jsx_preserve_mode = false;
93+
gentype_enabled = false;
9194
}
9295

9396
let default_filename (lang : Lang.t) = "playground." ^ Lang.to_string lang
@@ -475,6 +478,72 @@ module Compile = struct
475478
List.iter Iter.iter_structure_item structure.str_items;
476479
Js.array (!acc |> Array.of_list)
477480

481+
let gentype_output ~module_system ~modulename ~sourcefile structure env =
482+
let cmt_annots = Cmt_format.Implementation structure in
483+
let input_cmt =
484+
{
485+
Cmt_format.cmt_modname = modulename;
486+
cmt_annots;
487+
cmt_value_dependencies = [];
488+
cmt_comments = [];
489+
cmt_args = [||];
490+
cmt_sourcefile = Some sourcefile;
491+
cmt_builddir = Sys.getcwd ();
492+
cmt_loadpath = !Config.load_path;
493+
cmt_source_digest = None;
494+
cmt_initial_env = env;
495+
cmt_imports = [];
496+
cmt_interface_digest = None;
497+
cmt_use_summaries = false;
498+
cmt_extra_info = {Cmt_utils.deprecated_used = []};
499+
}
500+
in
501+
let has_gentype_annotations =
502+
GenTypeMain.cmt_check_annotations input_cmt
503+
~check_annotation:(fun ~loc:_ attributes ->
504+
attributes
505+
|> Annotation.get_attribute_payload
506+
Annotation.tag_is_one_of_the_gentype_annotations
507+
<> None)
508+
in
509+
if has_gentype_annotations then
510+
let module_ =
511+
match module_system with
512+
| Ext_module_system.Commonjs -> GenTypeConfig.CommonJS
513+
| Esmodule -> ESModule
514+
in
515+
let project_root = Sys.getcwd () in
516+
let config =
517+
{
518+
GenTypeConfig.default with
519+
module_;
520+
platform_lib = "rescript";
521+
project_root;
522+
bsb_project_root = project_root;
523+
}
524+
in
525+
let source_file = sourcefile in
526+
let output_file_relative =
527+
source_file |> Paths.get_output_file_relative ~config
528+
in
529+
let file_name = modulename |> ModuleName.from_string_unsafe in
530+
let resolver =
531+
ModuleResolver.create_lazy_resolver ~config
532+
~extensions:[".res"; ".shim.ts"] ~exclude_file:(fun fname ->
533+
fname = "React.res" || fname = "ReasonReact.res")
534+
in
535+
let code_text =
536+
input_cmt
537+
|> GenTypeMain.translate_c_m_t ~config ~output_file_relative ~resolver
538+
|> EmitJs.emit_translation_as_string ~config ~file_name
539+
~output_file_relative ~resolver
540+
~input_cmt_translate_type_declarations:
541+
GenTypeMain.input_cmt_translate_type_declarations
542+
in
543+
EmitType.file_header ~source_file:(Filename.basename source_file)
544+
^ "\n" ^ code_text ^ "\n"
545+
else "No @gentype annotations found."
546+
478547
let implementation ?(include_debug_outputs = false) ~(config : BundleConfig.t)
479548
~lang str =
480549
let {
@@ -483,6 +552,7 @@ module Compile = struct
483552
open_modules;
484553
experimental_features;
485554
jsx_preserve_mode;
555+
gentype_enabled;
486556
} =
487557
config
488558
in
@@ -551,6 +621,26 @@ module Compile = struct
551621
let lambda = Printer.to_string Printlambda.lambda lam in
552622
let lam, _ = Lam_convert.convert export_ident_sets lam in
553623
let lam = Lam_print.lambda_to_string lam in
624+
let gentype_attrs =
625+
if gentype_enabled then
626+
let structure, _ = typed_tree in
627+
Js.Unsafe.
628+
[|
629+
( "gentype",
630+
inject
631+
@@ Js.string
632+
(gentype_output ~module_system ~modulename
633+
~sourcefile:filename structure env) );
634+
|]
635+
else [||]
636+
in
637+
(* TODO(sourcemap PR): The developer playground already knows how to
638+
show an optional "source_map" debug tab. Add optional instance
639+
setters named "setSourceMapMode", "setSourceMapSourcesContent",
640+
and "setSourceMapRoot", matching getConfig fields named
641+
"source_map_mode", "source_map_sources_content", and
642+
"source_map_root", plus a compileWithDebug output field named
643+
"source_map". *)
554644
let debug_attrs =
555645
Js.Unsafe.
556646
[|
@@ -560,7 +650,7 @@ module Compile = struct
560650
("lam", inject @@ Js.string lam);
561651
|]
562652
in
563-
Js.Unsafe.obj (Array.append attrs debug_attrs)
653+
Js.Unsafe.obj (Array.concat [attrs; debug_attrs; gentype_attrs])
564654
else Js.Unsafe.obj attrs
565655
with e -> (
566656
match e with
@@ -661,6 +751,10 @@ module Export = struct
661751
config.jsx_preserve_mode <- value;
662752
true
663753
in
754+
let set_gentype_enabled value =
755+
config.gentype_enabled <- value;
756+
true
757+
in
664758
let convert_syntax ~(from_lang : string) ~(to_lang : string) (src : string)
665759
=
666760
let open Lang in
@@ -719,6 +813,10 @@ module Export = struct
719813
inject
720814
@@ Js.wrap_meth_callback (fun _ value ->
721815
Js.bool (set_jsx_preserve_mode (Js.to_bool value))) );
816+
( "setGentypeEnabled",
817+
inject
818+
@@ Js.wrap_meth_callback (fun _ value ->
819+
Js.bool (set_gentype_enabled (Js.to_bool value))) );
722820
( "getConfig",
723821
inject
724822
@@ Js.wrap_meth_callback (fun _ ->
@@ -733,6 +831,8 @@ module Export = struct
733831
("warn_flags", inject @@ Js.string config.warn_flags);
734832
( "jsx_preserve_mode",
735833
inject @@ (config.jsx_preserve_mode |> Js.bool) );
834+
( "gentype_enabled",
835+
inject @@ (config.gentype_enabled |> Js.bool) );
736836
( "experimental_features",
737837
inject
738838
@@ (config.experimental_features |> Array.of_list

packages/dev-playground/src/Bindings.res

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ module Instance = {
2828
@send external setWarnFlags: (compilerInstance, string) => unit = "setWarnFlags"
2929
@send external setFilename: (compilerInstance, string) => unit = "setFilename"
3030
@send external setJsxPreserveMode: (compilerInstance, bool) => unit = "setJsxPreserveMode"
31+
@send external setGentypeEnabled: (compilerInstance, bool) => unit = "setGentypeEnabled"
32+
@send external setSourceMapMode: (compilerInstance, string) => unit = "setSourceMapMode"
33+
@send
34+
external setSourceMapSourcesContent: (compilerInstance, bool) => unit =
35+
"setSourceMapSourcesContent"
36+
@send external setSourceMapRoot: (compilerInstance, string) => unit = "setSourceMapRoot"
3137
@send
3238
external setExperimentalFeatures: (compilerInstance, array<string>) => unit =
3339
"setExperimentalFeatures"
@@ -49,6 +55,11 @@ module Config = {
4955
@get external jsxPreserveMode: compilerConfig => option<bool> = "jsx_preserve_mode"
5056
@get
5157
external experimentalFeatures: compilerConfig => option<array<string>> = "experimental_features"
58+
@get external gentypeEnabled: compilerConfig => option<bool> = "gentype_enabled"
59+
@get external sourceMapMode: compilerConfig => option<string> = "source_map_mode"
60+
@get
61+
external sourceMapSourcesContent: compilerConfig => option<bool> = "source_map_sources_content"
62+
@get external sourceMapRoot: compilerConfig => option<string> = "source_map_root"
5263
}
5364

5465
module Diagnostic = {
@@ -68,6 +79,8 @@ module CompileResult = {
6879
@get external typedtree: compileResult => option<string> = "typedtree"
6980
@get external lambda: compileResult => option<string> = "lambda"
7081
@get external lam: compileResult => option<string> = "lam"
82+
@get external gentype: compileResult => option<string> = "gentype"
83+
@get external sourceMap: compileResult => option<string> = "source_map"
7184
@get external errors: compileResult => option<array<diagnostic>> = "errors"
7285
@get external warnings: compileResult => option<array<diagnostic>> = "warnings"
7386
@get external msg: compileResult => option<string> = "msg"

packages/dev-playground/src/CompilerApi.res

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ type info = {
2828
warnFlags: string,
2929
jsxPreserveMode: bool,
3030
experimentalFeatures: array<PlaygroundConfig.experimentalFeature>,
31+
gentypeEnabled: bool,
32+
sourceMapMode: PlaygroundConfig.sourceMapMode,
33+
sourceMapSourcesContent: bool,
34+
sourceMapRoot: string,
3135
libraries: array<string>,
3236
}
3337

@@ -37,6 +41,8 @@ type success = {
3741
typedtree: string,
3842
lambda: string,
3943
lam: string,
44+
gentype: option<string>,
45+
sourceMap: option<string>,
4046
warnings: array<string>,
4147
time: float,
4248
}
@@ -56,6 +62,10 @@ type normalizedConfig = {
5662
warnFlags: string,
5763
jsxPreserveMode: bool,
5864
experimentalFeatures: array<PlaygroundConfig.experimentalFeature>,
65+
gentypeEnabled: bool,
66+
sourceMapMode: PlaygroundConfig.sourceMapMode,
67+
sourceMapSourcesContent: bool,
68+
sourceMapRoot: string,
5969
}
6070

6171
let defaultWarnFlags = "+a-4-9-20-40-41-42-50-61-102-109"
@@ -68,6 +78,10 @@ let defaultConfig: PlaygroundConfig.t = {
6878
warnFlags: defaultWarnFlags,
6979
jsxPreserveMode: false,
7080
experimentalFeatures: [],
81+
gentypeEnabled: false,
82+
sourceMapMode: Disabled,
83+
sourceMapSourcesContent: true,
84+
sourceMapRoot: "",
7185
}
7286

7387
let pathFromBase = relativePath => {
@@ -147,6 +161,10 @@ let applyConfig = (
147161
~moduleSystem: PlaygroundConfig.moduleSystem,
148162
~warnFlags,
149163
~jsxPreserveMode,
164+
~gentypeEnabled,
165+
~sourceMapMode: PlaygroundConfig.sourceMapMode,
166+
~sourceMapSourcesContent,
167+
~sourceMapRoot,
150168
~experimentalFeatures: array<PlaygroundConfig.experimentalFeature>,
151169
) => {
152170
if hasFunction(instance, "setModuleSystem") {
@@ -161,6 +179,18 @@ let applyConfig = (
161179
if hasFunction(instance, "setJsxPreserveMode") {
162180
instance->Instance.setJsxPreserveMode(jsxPreserveMode)
163181
}
182+
if hasFunction(instance, "setGentypeEnabled") {
183+
instance->Instance.setGentypeEnabled(gentypeEnabled)
184+
}
185+
if hasFunction(instance, "setSourceMapMode") {
186+
instance->Instance.setSourceMapMode(sourceMapMode->PlaygroundConfig.sourceMapModeCompilerValue)
187+
}
188+
if hasFunction(instance, "setSourceMapSourcesContent") {
189+
instance->Instance.setSourceMapSourcesContent(sourceMapSourcesContent)
190+
}
191+
if hasFunction(instance, "setSourceMapRoot") {
192+
instance->Instance.setSourceMapRoot(sourceMapRoot)
193+
}
164194
if hasFunction(instance, "setExperimentalFeatures") {
165195
instance->Instance.setExperimentalFeatures(
166196
experimentalFeatures->Array.map(feature => (feature :> string)),
@@ -185,13 +215,27 @@ let experimentalFeaturesFromConfig = configValue =>
185215
| None => []
186216
}
187217

218+
let sourceMapModeFromConfig = configValue =>
219+
switch configValue->Config.sourceMapMode {
220+
| Some(sourceMapMode) =>
221+
switch sourceMapMode->PlaygroundConfig.parseSourceMapMode {
222+
| Some(sourceMapMode) => sourceMapMode
223+
| None => defaultConfig.sourceMapMode
224+
}
225+
| None => defaultConfig.sourceMapMode
226+
}
227+
188228
let normalizeConfig = (configValue: option<compilerConfig>): normalizedConfig =>
189229
switch configValue {
190230
| None => {
191231
moduleSystem: Esmodule,
192232
warnFlags: defaultConfig.warnFlags,
193233
jsxPreserveMode: false,
194234
experimentalFeatures: [],
235+
gentypeEnabled: defaultConfig.gentypeEnabled,
236+
sourceMapMode: defaultConfig.sourceMapMode,
237+
sourceMapSourcesContent: defaultConfig.sourceMapSourcesContent,
238+
sourceMapRoot: defaultConfig.sourceMapRoot,
195239
}
196240
| Some(configValue) => {
197241
moduleSystem: configValue->moduleSystemFromConfig,
@@ -204,6 +248,19 @@ let normalizeConfig = (configValue: option<compilerConfig>): normalizedConfig =>
204248
| None => false
205249
},
206250
experimentalFeatures: configValue->experimentalFeaturesFromConfig,
251+
gentypeEnabled: switch configValue->Config.gentypeEnabled {
252+
| Some(gentypeEnabled) => gentypeEnabled
253+
| None => defaultConfig.gentypeEnabled
254+
},
255+
sourceMapMode: configValue->sourceMapModeFromConfig,
256+
sourceMapSourcesContent: switch configValue->Config.sourceMapSourcesContent {
257+
| Some(sourceMapSourcesContent) => sourceMapSourcesContent
258+
| None => defaultConfig.sourceMapSourcesContent
259+
},
260+
sourceMapRoot: switch configValue->Config.sourceMapRoot {
261+
| Some(sourceMapRoot) => sourceMapRoot
262+
| None => defaultConfig.sourceMapRoot
263+
},
207264
}
208265
}
209266

@@ -291,7 +348,10 @@ let normalize = (compileOutput, elapsedMs): compileResult => {
291348
| None => ""
292349
}
293350

294-
Ok({jsCode, parsetree, typedtree, lambda, lam, warnings, time: elapsedMs})
351+
let gentype = compileOutput->CompileResult.gentype
352+
let sourceMap = compileOutput->CompileResult.sourceMap
353+
354+
Ok({jsCode, parsetree, typedtree, lambda, lam, gentype, sourceMap, warnings, time: elapsedMs})
295355

296356
| _ => Error(failureFromCompileOutput(compileOutput, elapsedMs))
297357
}
@@ -358,6 +418,10 @@ let ensureCompiler = async version => {
358418
~moduleSystem=Esmodule,
359419
~warnFlags=defaultConfig.warnFlags,
360420
~jsxPreserveMode=false,
421+
~gentypeEnabled=defaultConfig.gentypeEnabled,
422+
~sourceMapMode=defaultConfig.sourceMapMode,
423+
~sourceMapSourcesContent=defaultConfig.sourceMapSourcesContent,
424+
~sourceMapRoot=defaultConfig.sourceMapRoot,
361425
~experimentalFeatures=[],
362426
)
363427

@@ -410,6 +474,10 @@ let init = async version => {
410474
warnFlags: config.warnFlags,
411475
jsxPreserveMode: config.jsxPreserveMode,
412476
experimentalFeatures: config.experimentalFeatures,
477+
gentypeEnabled: config.gentypeEnabled,
478+
sourceMapMode: config.sourceMapMode,
479+
sourceMapSourcesContent: config.sourceMapSourcesContent,
480+
sourceMapRoot: config.sourceMapRoot,
413481
libraries,
414482
}
415483
}
@@ -423,6 +491,10 @@ let compile = async (source, config: PlaygroundConfig.t) => {
423491
~moduleSystem=config.moduleSystem,
424492
~warnFlags=config.warnFlags,
425493
~jsxPreserveMode=config.jsxPreserveMode,
494+
~gentypeEnabled=config.gentypeEnabled,
495+
~sourceMapMode=config.sourceMapMode,
496+
~sourceMapSourcesContent=config.sourceMapSourcesContent,
497+
~sourceMapRoot=config.sourceMapRoot,
426498
~experimentalFeatures=config.experimentalFeatures,
427499
)
428500

@@ -447,6 +519,10 @@ let format = async (source, config: PlaygroundConfig.t) => {
447519
~moduleSystem=config.moduleSystem,
448520
~warnFlags=config.warnFlags,
449521
~jsxPreserveMode=config.jsxPreserveMode,
522+
~gentypeEnabled=config.gentypeEnabled,
523+
~sourceMapMode=config.sourceMapMode,
524+
~sourceMapSourcesContent=config.sourceMapSourcesContent,
525+
~sourceMapRoot=config.sourceMapRoot,
450526
~experimentalFeatures=config.experimentalFeatures,
451527
)
452528

0 commit comments

Comments
 (0)