diff --git a/src/ConsolePanel.res b/src/ConsolePanel.res index b7bba9587..6c72f86f0 100644 --- a/src/ConsolePanel.res +++ b/src/ConsolePanel.res @@ -25,9 +25,11 @@ let make = (~logs, ~appendLog) => {

{React.string("Console")}

{switch logs { | [] => - React.string( - "Add some 'Console.log' to your code and click 'Run' or enable 'Auto-run' to see your logs here.", - ) +

+ {React.string( + "Add some 'Console.log' to your code and click 'Run' or enable 'Auto-run' to see your logs here.", + )} +

| logs => let content = logs diff --git a/src/Playground.res b/src/Playground.res index 8ea138658..76511a5aa 100644 --- a/src/Playground.res +++ b/src/Playground.res @@ -1,14 +1,3 @@ -/* - TODO / Idea list: - - Fix issue with Reason where a comment on the last line causes a infinite loop - - Add settings pane to set moduleSystem - - Add advanced mode for enabling OCaml output as well - - More advanced tasks: - - Fix syntax convertion issue where comments are stripped on Reason <-> Res convertion - - Try to get Reason's recoverable errors working - */ - %%raw(` if (typeof window !== "undefined" && typeof window.navigator !== "undefined") { require("codemirror/mode/javascript/javascript"); @@ -42,6 +31,22 @@ module DropdownSelect = { } module ToggleSelection = { + module SelectionOption = { + @react.component + let make = (~label, ~isActive, ~disabled, ~onClick) => { + + } + } + @react.component let make = ( ~onChange: 'a => unit, @@ -58,41 +63,21 @@ module ToggleSelection = { values } - let selectedIndex = switch Belt.Array.getIndexBy(values, lang => lang === selected) { - | Some(i) => i - | None => 0 - } - - let elements = Array.mapWithIndex(values, (value, i) => { - let active = i === selectedIndex ? "bg-fire text-white font-bold" : "bg-gray-80 opacity-50" - let label = toLabel(value) - - let onMouseDown = evt => { - ReactEvent.Mouse.preventDefault(evt) - ReactEvent.Mouse.stopPropagation(evt) - - if i !== selectedIndex { - switch values[i] { - | Some(value) => onChange(value) - | None => () +
+ {values + ->Array.map(value => { + let label = toLabel(value) + let isActive = value === selected + let onClick = _event => { + if !isActive { + onChange(value) } } - } - - // Required for iOS Safari 12 - let onClick = _ => () - - - }) -
{React.array(elements)}
+ + }) + ->React.array} +
} } @@ -697,9 +682,9 @@ module WarningFlagsWidget = { }) ->React.array ->Some - | Typing(typing) => + | Typing(typing) if typing.suggestion != NoSuggestion => let suggestions = switch typing.suggestion { - | NoSuggestion => React.string("Type + / - followed by a number or letter (e.g. +a+1)") + | NoSuggestion => React.null | ErrorSuggestion(msg) => React.string(msg) | FuzzySuggestions({precedingTokens, selected, results, modifier}) => Array.mapWithIndex(results, ((flag, desc), i) => { @@ -753,7 +738,8 @@ module WarningFlagsWidget = { })->React.array } Some(suggestions) - | HideSuggestion(_) => None + + | Typing(_) | HideSuggestion(_) => None } let suggestionBox = @@ -793,20 +779,12 @@ module WarningFlagsWidget = { | [] | [{enabled: false, flag: "a"}] => React.null | _ => - let onMouseDown = evt => { - ReactEvent.Mouse.preventDefault(evt) + let onClick = _evt => { onUpdate([{WarningFlagDescription.Parser.enabled: false, flag: "a"}]) } - // For iOS12 compat - let onClick = _ => () - let onFocus = evt => { - ReactEvent.Focus.preventDefault(evt) - ReactEvent.Focus.stopPropagation(evt) - } - @@ -1334,6 +1310,56 @@ module InitialContent = { } } +module App = { + @react.component + let make = () => { + let (count, setCount) = React.useState(() => 0) + let (username, setUsername) = React.useState(() => "Anonymous") + +
+ {React.string("Username: ")} + { + event->ReactEvent.Form.preventDefault + let eventTarget = event->ReactEvent.Form.target + let username = eventTarget["value"] + setUsername(_prev => username) + }} + /> + + + +
+ } +} +` + + let since_11 = `module CounterMessage = { + @react.component + let make = (~count, ~username=?) => { + let times = switch count { + | 1 => "once" + | 2 => "twice" + | n => Int.toString(n) ++ " times" + } + + let name = switch username { + | Some("") => "Anonymous" + | Some(name) => name + | None => "Anonymous" + } + +
{React.string(\`Hello \$\{name\}, you clicked me \` ++ times)}
+ } +} + module App = { @react.component let make = () => { @@ -1412,11 +1438,10 @@ let make = (~versions: array) => { let initialContent = switch (Dict.get(router.query, "code"), initialLang) { | (Some(compressedCode), _) => LzString.decompressToEncodedURIComponent(compressedCode) | (None, Reason) => initialReContent - | (None, Res) - | (None, _) => + | (None, Res) => switch initialVersion { | Some({major: 10, minor}) if minor >= 1 => InitialContent.since_10_1 - | Some({major}) if major > 10 => InitialContent.since_10_1 + | Some({major}) if major > 10 => InitialContent.since_11 | _ => InitialContent.original } } @@ -1661,23 +1686,74 @@ let make = (~versions: array) => { let headers = Array.mapWithIndex(tabs, (tab, i) => { let title = switch tab { - | Output => "Output" - | JavaScript => "JavaScript" - | Problems => "Problems" - | Settings => "Settings" + | Output => "Output"->React.string + + | JavaScript => "JavaScript"->React.string + + | Problems => { + let problemCounts: {"warnings": int, "errors": int} = switch compilerState { + | Compiling({state: ready}) + | Ready(ready) + | Executing({state: ready}) + | SwitchingCompiler(ready, _) => { + "warnings": switch ready.result { + | Comp(Success({warnings})) => warnings->Array.length + | _ => 0 + }, + "errors": switch ready.result { + | FinalResult.Comp(Fail(result)) => + switch result { + | SyntaxErr(errors) | TypecheckErr(errors) | OtherErr(errors) => errors->Array.length + | WarningErr(errors) => errors->Array.length + | WarningFlagErr(_) => 1 + } + | Conv(Fail({details})) => details->Array.length + | Comp(Success(_)) => 0 + | Conv(Success(_)) => 0 + | Comp(UnexpectedError(_)) + | Conv(UnexpectedError(_)) + | Comp(Unknown(_)) + | Conv(Unknown(_)) => 1 + | Nothing => 0 + }, + } + + | SetupFailed(_) | Init => { + "warnings": 0, + "errors": 0, + } + } + +
+ {"Problems"->React.string} + {if problemCounts["errors"] > 0 { + + {problemCounts["errors"]->React.int} + + } else { + React.null + }} + {if problemCounts["warnings"] > 0 { + + {problemCounts["warnings"]->React.int} + + } else { + React.null + }} +
+ } + + | Settings => "Settings"->React.string } - let onMouseDown = evt => { + + let onClick = evt => { ReactEvent.Mouse.preventDefault(evt) ReactEvent.Mouse.stopPropagation(evt) setCurrentTab(_ => tab) } let active = currentTab === tab - // For Safari iOS12 - let onClick = _ => () let className = makeTabClass(active) - + })
diff --git a/src/RenderPanel.res b/src/RenderPanel.res index 961430cf0..08453675f 100644 --- a/src/RenderPanel.res +++ b/src/RenderPanel.res @@ -4,9 +4,11 @@ let make = (~validReact) => {

{React.string("React")}

{validReact ? React.null - : React.string( - "Create a React component called 'App' if you want to render it here, then click 'Run' or enable 'Auto-run'.", - )} + :

+ {React.string( + "Create a React component called 'App' if you want to render it here, then click 'Run' or enable 'Auto-run'.", + )} +

}
diff --git a/src/bindings/RescriptCompilerApi.res b/src/bindings/RescriptCompilerApi.res index af966350d..f032a6f62 100644 --- a/src/bindings/RescriptCompilerApi.res +++ b/src/bindings/RescriptCompilerApi.res @@ -3,27 +3,23 @@ module Lang = { type t = | Reason - | OCaml | Res let toString = t => switch t { | Res => "ReScript" | Reason => "Reason" - | OCaml => "OCaml" } let toExt = t => switch t { | Res => "res" | Reason => "re" - | OCaml => "ml" } let decode = (json): t => { open! Json.Decode switch string(json) { - | "ml" => OCaml | "re" => Reason | "res" => Res | other => raise(DecodeError(`Unknown language "${other}"`)) @@ -419,17 +415,6 @@ module Compiler = { } } - @send @scope("ocaml") - external ocamlCompile: (t, string) => JSON.t = "compile" - - let ocamlCompile = (t, code): CompilationResult.t => { - let startTime = now() - let json = ocamlCompile(t, code) - let stopTime = now() - - CompilationResult.decode(~time=stopTime -. startTime, json) - } - @send external getConfig: t => Config.t = "getConfig" @send external setFilename: (t, string) => bool = "setFilename" diff --git a/src/bindings/RescriptCompilerApi.resi b/src/bindings/RescriptCompilerApi.resi index de8c069d4..e156604bb 100644 --- a/src/bindings/RescriptCompilerApi.resi +++ b/src/bindings/RescriptCompilerApi.resi @@ -9,7 +9,6 @@ module Lang: { type t = | Reason - | OCaml | Res let toString: t => string @@ -192,7 +191,6 @@ module Compiler: { * OCaml compiler actions (Note: no pretty print available for OCaml) */ let ocamlVersion: t => option - let ocamlCompile: (t, string) => CompilationResult.t /* * Config setter / getters diff --git a/src/common/CompilerManagerHook.res b/src/common/CompilerManagerHook.res index b3257a0c2..39c0e214e 100644 --- a/src/common/CompilerManagerHook.res +++ b/src/common/CompilerManagerHook.res @@ -320,7 +320,6 @@ let useCompilerManager = ( let convResult = switch ready.targetLang { | Res => instance->Compiler.resFormat(code)->Some | Reason => instance->Compiler.reasonFormat(code)->Some - | _ => None } let result = switch convResult { @@ -511,13 +510,11 @@ let useCompilerManager = ( let compResult = switch apiVersion { | V1 => switch lang { - | Lang.OCaml => instance->Compiler.ocamlCompile(code) | Lang.Reason => instance->Compiler.reasonCompile(code) | Lang.Res => instance->Compiler.resCompile(code) } | V2 | V3 | V4 => switch lang { - | Lang.OCaml => instance->Compiler.ocamlCompile(code) | Lang.Reason => CompilationResult.UnexpectedError( `Reason not supported with API version "${apiVersion->RescriptCompilerApi.Version.toString}"`, diff --git a/src/common/WarningFlagDescription.res b/src/common/WarningFlagDescription.res index b7890d6a3..4c40c153e 100644 --- a/src/common/WarningFlagDescription.res +++ b/src/common/WarningFlagDescription.res @@ -7,7 +7,6 @@ let numeric = [ "Fragile pattern matching: matching that will remain complete even if additional constructors are added to one of the variant types matched.", ), (5, "Partially applied function: expression whose result has function type and is ignored."), - (6, "Label omitted in function application."), (8, "Partial match: missing cases in pattern-matching."), (9, "Missing fields in a record pattern."), ( @@ -41,6 +40,7 @@ let numeric = [ (37, "Unused constructor."), (38, "Unused extension constructor."), (39, "Unused rec flag."), + (41, "Ambiguous constructor or label name."), (43, "Nonoptional label applied as optional."), (44, "Open statement shadows an already defined identifier."), (45, "Open statement shadows an already defined label or constructor."), @@ -56,7 +56,6 @@ let numeric = [ (57, "Ambiguous or-pattern variables under guard"), (59, "Assignment to non-mutable value"), (60, "Unused module declaration"), - (61, "Unboxable type in primitive declaration"), (62, "Type constraint on GADT type declaration"), (101, "Unused bs attributes"), (102, "Polymorphic comparison introduced (maybe unsafe)"),