Skip to content

Commit 85e6546

Browse files
Developer playground: genType support and sourcemap scaffolding
1 parent 0782ee3 commit 85e6546

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
@@ -30,6 +30,12 @@ module Instance = {
3030
@send external setWarnFlags: (compilerInstance, string) => unit = "setWarnFlags"
3131
@send external setFilename: (compilerInstance, string) => unit = "setFilename"
3232
@send external setJsxPreserveMode: (compilerInstance, bool) => unit = "setJsxPreserveMode"
33+
@send external setGentypeEnabled: (compilerInstance, bool) => unit = "setGentypeEnabled"
34+
@send external setSourceMapMode: (compilerInstance, string) => unit = "setSourceMapMode"
35+
@send
36+
external setSourceMapSourcesContent: (compilerInstance, bool) => unit =
37+
"setSourceMapSourcesContent"
38+
@send external setSourceMapRoot: (compilerInstance, string) => unit = "setSourceMapRoot"
3339
@send
3440
external setExperimentalFeatures: (compilerInstance, array<string>) => unit =
3541
"setExperimentalFeatures"
@@ -51,6 +57,11 @@ module Config = {
5157
@get external jsxPreserveMode: compilerConfig => option<bool> = "jsx_preserve_mode"
5258
@get
5359
external experimentalFeatures: compilerConfig => option<array<string>> = "experimental_features"
60+
@get external gentypeEnabled: compilerConfig => option<bool> = "gentype_enabled"
61+
@get external sourceMapMode: compilerConfig => option<string> = "source_map_mode"
62+
@get
63+
external sourceMapSourcesContent: compilerConfig => option<bool> = "source_map_sources_content"
64+
@get external sourceMapRoot: compilerConfig => option<string> = "source_map_root"
5465
}
5566

5667
module Diagnostic = {
@@ -70,6 +81,8 @@ module CompileResult = {
7081
@get external typedtree: compileResult => option<string> = "typedtree"
7182
@get external lambda: compileResult => option<string> = "lambda"
7283
@get external lam: compileResult => option<string> = "lam"
84+
@get external gentype: compileResult => option<string> = "gentype"
85+
@get external sourceMap: compileResult => option<string> = "source_map"
7386
@get external errors: compileResult => option<array<diagnostic>> = "errors"
7487
@get external warnings: compileResult => option<array<diagnostic>> = "warnings"
7588
@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
@@ -50,6 +50,10 @@ type info = {
5050
warnFlags: string,
5151
jsxPreserveMode: bool,
5252
experimentalFeatures: array<PlaygroundConfig.experimentalFeature>,
53+
gentypeEnabled: bool,
54+
sourceMapMode: PlaygroundConfig.sourceMapMode,
55+
sourceMapSourcesContent: bool,
56+
sourceMapRoot: string,
5357
libraries: array<string>,
5458
}
5559

@@ -59,6 +63,8 @@ type success = {
5963
typedtree: string,
6064
lambda: string,
6165
lam: string,
66+
gentype: option<string>,
67+
sourceMap: option<string>,
6268
warnings: array<string>,
6369
time: float,
6470
}
@@ -78,6 +84,10 @@ type normalizedConfig = {
7884
warnFlags: string,
7985
jsxPreserveMode: bool,
8086
experimentalFeatures: array<PlaygroundConfig.experimentalFeature>,
87+
gentypeEnabled: bool,
88+
sourceMapMode: PlaygroundConfig.sourceMapMode,
89+
sourceMapSourcesContent: bool,
90+
sourceMapRoot: string,
8191
}
8292

8393
let defaultWarnFlags = "+a-4-9-20-40-41-42-50-61-102-109"
@@ -90,6 +100,10 @@ let defaultConfig: PlaygroundConfig.t = {
90100
warnFlags: defaultWarnFlags,
91101
jsxPreserveMode: false,
92102
experimentalFeatures: [],
103+
gentypeEnabled: false,
104+
sourceMapMode: Disabled,
105+
sourceMapSourcesContent: true,
106+
sourceMapRoot: "",
93107
}
94108

95109
let pathFromBase = relativePath => {
@@ -207,6 +221,10 @@ let applyConfig = (
207221
~moduleSystem: PlaygroundConfig.moduleSystem,
208222
~warnFlags,
209223
~jsxPreserveMode,
224+
~gentypeEnabled,
225+
~sourceMapMode: PlaygroundConfig.sourceMapMode,
226+
~sourceMapSourcesContent,
227+
~sourceMapRoot,
210228
~experimentalFeatures: array<PlaygroundConfig.experimentalFeature>,
211229
) => {
212230
if hasFunction(instance, "setModuleSystem") {
@@ -221,6 +239,18 @@ let applyConfig = (
221239
if hasFunction(instance, "setJsxPreserveMode") {
222240
instance->Instance.setJsxPreserveMode(jsxPreserveMode)
223241
}
242+
if hasFunction(instance, "setGentypeEnabled") {
243+
instance->Instance.setGentypeEnabled(gentypeEnabled)
244+
}
245+
if hasFunction(instance, "setSourceMapMode") {
246+
instance->Instance.setSourceMapMode(sourceMapMode->PlaygroundConfig.sourceMapModeCompilerValue)
247+
}
248+
if hasFunction(instance, "setSourceMapSourcesContent") {
249+
instance->Instance.setSourceMapSourcesContent(sourceMapSourcesContent)
250+
}
251+
if hasFunction(instance, "setSourceMapRoot") {
252+
instance->Instance.setSourceMapRoot(sourceMapRoot)
253+
}
224254
if hasFunction(instance, "setExperimentalFeatures") {
225255
instance->Instance.setExperimentalFeatures(
226256
experimentalFeatures->Array.map(feature => (feature :> string)),
@@ -245,13 +275,27 @@ let experimentalFeaturesFromConfig = configValue =>
245275
| None => []
246276
}
247277

278+
let sourceMapModeFromConfig = configValue =>
279+
switch configValue->Config.sourceMapMode {
280+
| Some(sourceMapMode) =>
281+
switch sourceMapMode->PlaygroundConfig.parseSourceMapMode {
282+
| Some(sourceMapMode) => sourceMapMode
283+
| None => defaultConfig.sourceMapMode
284+
}
285+
| None => defaultConfig.sourceMapMode
286+
}
287+
248288
let normalizeConfig = (configValue: option<compilerConfig>): normalizedConfig =>
249289
switch configValue {
250290
| None => {
251291
moduleSystem: Esmodule,
252292
warnFlags: defaultConfig.warnFlags,
253293
jsxPreserveMode: false,
254294
experimentalFeatures: [],
295+
gentypeEnabled: defaultConfig.gentypeEnabled,
296+
sourceMapMode: defaultConfig.sourceMapMode,
297+
sourceMapSourcesContent: defaultConfig.sourceMapSourcesContent,
298+
sourceMapRoot: defaultConfig.sourceMapRoot,
255299
}
256300
| Some(configValue) => {
257301
moduleSystem: configValue->moduleSystemFromConfig,
@@ -264,6 +308,19 @@ let normalizeConfig = (configValue: option<compilerConfig>): normalizedConfig =>
264308
| None => false
265309
},
266310
experimentalFeatures: configValue->experimentalFeaturesFromConfig,
311+
gentypeEnabled: switch configValue->Config.gentypeEnabled {
312+
| Some(gentypeEnabled) => gentypeEnabled
313+
| None => defaultConfig.gentypeEnabled
314+
},
315+
sourceMapMode: configValue->sourceMapModeFromConfig,
316+
sourceMapSourcesContent: switch configValue->Config.sourceMapSourcesContent {
317+
| Some(sourceMapSourcesContent) => sourceMapSourcesContent
318+
| None => defaultConfig.sourceMapSourcesContent
319+
},
320+
sourceMapRoot: switch configValue->Config.sourceMapRoot {
321+
| Some(sourceMapRoot) => sourceMapRoot
322+
| None => defaultConfig.sourceMapRoot
323+
},
267324
}
268325
}
269326

@@ -351,7 +408,10 @@ let normalize = (compileOutput, elapsedMs): compileResult => {
351408
| None => ""
352409
}
353410

354-
Ok({jsCode, parsetree, typedtree, lambda, lam, warnings, time: elapsedMs})
411+
let gentype = compileOutput->CompileResult.gentype
412+
let sourceMap = compileOutput->CompileResult.sourceMap
413+
414+
Ok({jsCode, parsetree, typedtree, lambda, lam, gentype, sourceMap, warnings, time: elapsedMs})
355415

356416
| _ => Error(failureFromCompileOutput(compileOutput, elapsedMs))
357417
}
@@ -418,6 +478,10 @@ let ensureCompiler = async version => {
418478
~moduleSystem=Esmodule,
419479
~warnFlags=defaultConfig.warnFlags,
420480
~jsxPreserveMode=false,
481+
~gentypeEnabled=defaultConfig.gentypeEnabled,
482+
~sourceMapMode=defaultConfig.sourceMapMode,
483+
~sourceMapSourcesContent=defaultConfig.sourceMapSourcesContent,
484+
~sourceMapRoot=defaultConfig.sourceMapRoot,
421485
~experimentalFeatures=[],
422486
)
423487

@@ -470,6 +534,10 @@ let init = async version => {
470534
warnFlags: config.warnFlags,
471535
jsxPreserveMode: config.jsxPreserveMode,
472536
experimentalFeatures: config.experimentalFeatures,
537+
gentypeEnabled: config.gentypeEnabled,
538+
sourceMapMode: config.sourceMapMode,
539+
sourceMapSourcesContent: config.sourceMapSourcesContent,
540+
sourceMapRoot: config.sourceMapRoot,
473541
libraries,
474542
}
475543
}
@@ -483,6 +551,10 @@ let compile = async (source, config: PlaygroundConfig.t) => {
483551
~moduleSystem=config.moduleSystem,
484552
~warnFlags=config.warnFlags,
485553
~jsxPreserveMode=config.jsxPreserveMode,
554+
~gentypeEnabled=config.gentypeEnabled,
555+
~sourceMapMode=config.sourceMapMode,
556+
~sourceMapSourcesContent=config.sourceMapSourcesContent,
557+
~sourceMapRoot=config.sourceMapRoot,
486558
~experimentalFeatures=config.experimentalFeatures,
487559
)
488560

@@ -507,6 +579,10 @@ let format = async (source, config: PlaygroundConfig.t) => {
507579
~moduleSystem=config.moduleSystem,
508580
~warnFlags=config.warnFlags,
509581
~jsxPreserveMode=config.jsxPreserveMode,
582+
~gentypeEnabled=config.gentypeEnabled,
583+
~sourceMapMode=config.sourceMapMode,
584+
~sourceMapSourcesContent=config.sourceMapSourcesContent,
585+
~sourceMapRoot=config.sourceMapRoot,
510586
~experimentalFeatures=config.experimentalFeatures,
511587
)
512588

0 commit comments

Comments
 (0)