Skip to content

Commit d762ea0

Browse files
committed
Upgrade gen_js_api to 1.0.9
1 parent 3c9ee20 commit d762ea0

File tree

6 files changed

+51
-41
lines changed

6 files changed

+51
-41
lines changed

dist_jsoo/ts2ocaml-jsoo-stdlib.opam

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ bug-reports: "https://github.com/ocsigen/ts2ocaml/issues"
1313
depends: [
1414
"dune" {>= "2.7"}
1515
"ocaml" {>= "4.08"}
16-
"ojs" {>= "1.0.8"}
16+
"ojs" {>= "1.0.9"}
1717
"odoc" {with-doc}
1818
]
1919
build: [

docs/development.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,12 @@ Modules with **\[\<AutoOpen\>\]** does not require `open` to use.
3737

3838
- [.NET SDK 5.0](https://dotnet.microsoft.com/download/dotnet/5.0)
3939
- [FAKE](https://fake.build/) and [Fable](https://fable.io/) are required to build this tool.
40-
- Run `dotnet tool restore` in the root directory of this repo to install them.
40+
- Run `dotnet tool restore` in the root directory of this repo to install them.
4141

4242
- OCaml 4.08 or higher
4343
- [js_of_ocaml](https://github.com/ocsigen/js_of_ocaml) should be installed to your opam switch.
44-
- The latest [gen_js_api](https://github.com/LexiFi/gen_js_api) should also be installed to your opam switch.
45-
- As of Oct 2021, most of the required features have not been present in the latest version in opam.
46-
- You should install the latest version by `opam pin add gen_js_api https://github.com/LexiFi/gen_js_api.git`
44+
- [gen_js_api](https://github.com/LexiFi/gen_js_api) `>= 1.0.9` should also be installed to your opam switch.
45+
- Run `opam install . --deps-only` to install all the dependencies.
4746

4847
- Node 14.0 or higher
4948
- [yarn](https://yarnpkg.com/) is required.

docs/js_of_ocaml.md

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,7 @@ The documentation for the `ts2ocaml` command and its options comes after the wal
1515

1616
`ts2ocaml` for `js_of_ocaml` generates `.mli` files, which should then be processed with [`LexiFi/gen_js_api`](https://github.com/LexiFi/gen_js_api).
1717

18-
You should use the latest `gen_js_api` as `ts2ocaml` uses the latest features of `gen_js_api`.
19-
As of Oct 2021, most of the required features have not been present in the latest version in opam.
20-
So you would have to either do
21-
22-
* `opam pin add gen_js_api https://github.com/LexiFi/gen_js_api.git` **(recommended)**, or
23-
* `git submodule` [their repository](https://github.com/LexiFi/gen_js_api) to the `lib` directory of your OCaml project.
24-
- Note that if you use `gen_js_api` via a submodule, it might conflict with [`ts2ocaml-jsoo-stdlib`](#using-ts2ocaml-jsoo-stdlib-package) which is installed via `ocaml pin add`.
25-
- Therefore, this would work only if you are going to do [`ts2ocaml jsoo --create-minimal-stdlib`](#using---create-minimal-stdlib--create-minimal-stdlib).
18+
You should use `gen_js_api` version 1.0.9 or higher, as `ts2ocaml` uses the latest features of `gen_js_api`.
2619

2720
## Adding the standard library
2821

@@ -40,8 +33,7 @@ To fulfill both needs, we've made two ways to add the standard library.
4033

4134
This package contains the full bindings for JS, DOM, and Web Worker API, generated with the [`full` preset](#choosing-a-preset).
4235

43-
As described in [Requirements](#requirements), `ts2ocaml` needs the latest `gen_js_api`, which is still not present in OPAM repository.
44-
So, `ts2ocaml-jsoo-stdlib` is currently **not in OPAM repository**.
36+
`ts2ocaml-jsoo-stdlib` is currently **not in OPAM repository**.
4537

4638
To install it to your OPAM switch, we recommend you to use [`opam pin`](https://opam.ocaml.org/doc/Usage.html#opam-pin).
4739

src/Targets/JsOfOCaml/Writer.fs

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,17 @@ let anonymousInterfaceToIdentifier (ctx: Context) (c: Class) : text =
9898
| None, None -> failwithf "the anonymous interface '%A' is not found in the context" c
9999
| _, Some n -> failwithf "the class or interface '%s' is not anonymous" n
100100

101+
let enumCaseToIdentifier (e: Enum) (c: EnumCase) =
102+
let duplicateCases =
103+
e.cases |> List.filter (fun c' -> c.value = c'.value)
104+
match duplicateCases with
105+
| [] -> failwith "impossible_enumCaseToIdentifier"
106+
| [c'] ->
107+
assert (c = c')
108+
Naming.constructorName [c.name]
109+
| cs ->
110+
cs |> List.map (fun c -> c.name) |> Naming.constructorName
111+
101112
type Variance = Covariant | Contravariant | Invariant with
102113
static member (~-) (v: Variance) =
103114
match v with
@@ -149,13 +160,21 @@ module OverrideFunc =
149160
let rec emitTypeImpl (flags: EmitTypeFlags) (overrideFunc: OverrideFunc) (ctx: Context) (ty: Type) : text =
150161
let forceSkipAttr text =
151162
if flags.forceSkipAttributes then empty else text
152-
let treatEnum (flags: EmitTypeFlags) ctx (cases: Set<Choice<EnumCase, Literal>>) =
163+
let treatEnum (flags: EmitTypeFlags) ctx (cases: Set<Choice<Enum * EnumCase, Literal>>) =
164+
let usedValues =
165+
cases
166+
|> Seq.choose (function Choice1Of2 (_, { value = v }) -> v | _ -> None)
167+
|> Set.ofSeq
168+
let cases =
169+
cases
170+
// Remove literal cases (e.g. `42`) when it is a duplicate of some enum case (e.g. `Case = 42`).
171+
|> Set.filter (function Choice2Of2 l when usedValues |> Set.contains l -> false | _ -> true)
172+
// Convert to identifiers while merging duplicate enum cases
173+
|> Set.map (function
174+
| Choice1Of2 (e, c) -> enumCaseToIdentifier e c |> str, c.value
175+
| Choice2Of2 l -> "L_" @+ literalToIdentifier ctx l, Some l)
153176
between "[" "]" (concat (str " | ") [
154-
for c in Set.toSeq cases do
155-
let name, value =
156-
match c with
157-
| Choice1Of2 e -> str (Naming.constructorName [e.name]), e.value
158-
| Choice2Of2 l -> "L_" @+ literalToIdentifier ctx l, Some l
177+
for name, value in Set.toSeq cases do
159178
let attr =
160179
match value with
161180
| _ when flags.forceSkipAttributes -> empty
@@ -333,7 +352,7 @@ let rec emitTypeImpl (flags: EmitTypeFlags) (overrideFunc: OverrideFunc) (ctx: C
333352
failwith "impossible_emitResolvedUnion_treatOther_go"
334353
else
335354
otherTypes |> Set.toList |> List.map (emitTypeImpl flags overrideFunc ctx) |> safe_union_t
336-
let treatEnumOr (cases: Set<Choice<EnumCase, Literal>>) t =
355+
let treatEnumOr (cases: Set<Choice<Enum * EnumCase, Literal>>) t =
337356
if Set.isEmpty cases then t
338357
else Type.enum_or (treatEnum flags ctx cases) t
339358
let treatDUMany du =
@@ -795,16 +814,19 @@ module GetSelfTyText =
795814
else fallback
796815
| None -> fallback
797816

798-
let enumCases (cases: EnumCase list) =
817+
let enumCases (e: Enum) (cases: EnumCase list) =
818+
let cases =
819+
cases
820+
|> List.map (fun c -> enumCaseToIdentifier e c, c.value)
821+
|> Set.ofList
799822
between "[" "]" (concat (str " | ") [
800-
for c in cases do
801-
let name, value = str (Naming.constructorName [c.name]), c.value
823+
for name, value in cases |> Set.toSeq do
802824
let attr =
803825
match value with
804826
| Some v -> Attr.js (Term.literal v)
805827
| None -> empty
806-
yield pv_head @+ name + attr
807-
]) +@ " [@js.enum]"
828+
yield pv_head @+ name @+ attr
829+
]) +@ " [@js.enum]"
808830

809831
let getExportFromStatement (ctx: Context) (name: string) (kind: Kind list) (kindString: string) (s: Statement) : ExportWithKind option =
810832
let fn = ctx |> Context.getFullName [name]
@@ -1107,15 +1129,15 @@ let createStructuredText (rootCtx: Context) (stmts: Statement list) : Structured
11071129
| EnumDef e ->
11081130
let module' =
11091131
let ctx = ctx |> Context.ofChildNamespace e.name
1110-
let items = emitTypeAliases emitTypeFlags OverrideFunc.noOverride ctx [] (GetSelfTyText.enumCases e.cases)
1132+
let items = emitTypeAliases emitTypeFlags OverrideFunc.noOverride ctx [] (GetSelfTyText.enumCases e e.cases)
11111133
let node = {| StructuredTextNode.empty with items = items; docCommentLines = comments; knownTypes = knownTypes () |}
11121134
let module' =
11131135
getModule e.name |> Trie.setOrUpdate node StructuredTextNode.union
11141136
e.cases |> List.fold (fun state c ->
11151137
let ctx = ctx |> Context.ofChildNamespace c.name
11161138
let comments = List.map emitCommentBody c.comments
11171139
let items =
1118-
emitTypeAliases emitTypeFlags OverrideFunc.noOverride ctx [] (GetSelfTyText.enumCases [c])
1140+
emitTypeAliases emitTypeFlags OverrideFunc.noOverride ctx [] (GetSelfTyText.enumCases e [c])
11191141
let node = {| StructuredTextNode.empty with items = items; docCommentLines = comments; knownTypes = knownTypes () |}
11201142
state |> Trie.addOrUpdate [c.name] node StructuredTextNode.union
11211143
) module'
@@ -1365,9 +1387,9 @@ let emitFlattenedDefinitions (ctx: Context) (stmts: Statement list) : text list
13651387
| EnumDef e ->
13661388
let fn = List.rev (e.name :: ctx.currentNamespace)
13671389
[
1368-
yield tprintf "%s %s = " prefix (Naming.flattenedTypeName fn) + GetSelfTyText.enumCases e.cases
1390+
yield tprintf "%s %s = " prefix (Naming.flattenedTypeName fn) + GetSelfTyText.enumCases e e.cases
13691391
for c in e.cases do
1370-
yield tprintf "and %s = " (Naming.flattenedTypeName (fn @ [c.name])) + GetSelfTyText.enumCases [c]
1392+
yield tprintf "and %s = " (Naming.flattenedTypeName (fn @ [c.name])) + GetSelfTyText.enumCases e [c]
13711393
]
13721394
| ClassDef c ->
13731395
match c.name with

src/Typer.fs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,7 +1318,7 @@ type ResolvedUnion = {
13181318
caseUndefined: bool
13191319
typeofableTypes: Set<TypeofableType>
13201320
caseArray: Set<Type> option
1321-
caseEnum: Set<Choice<EnumCase, Literal>>
1321+
caseEnum: Set<Choice<Enum * EnumCase, Literal>>
13221322
discriminatedUnions: Map<string, Map<Literal, Type>>
13231323
otherTypes: Set<Type>
13241324
}
@@ -1347,8 +1347,8 @@ module ResolvedUnion =
13471347
ru.caseEnum
13481348
|> Set.toSeq
13491349
|> Seq.map (function
1350-
| Choice1Of2 { name = name; value = Some value } -> sprintf "%s=%s" name (Literal.toString value)
1351-
| Choice1Of2 { name = name; value = None } -> sprintf "%s=?" name
1350+
| Choice1Of2 ({ name = ty }, { name = name; value = Some value }) -> sprintf "%s.%s=%s" ty name (Literal.toString value)
1351+
| Choice1Of2 ({ name = ty }, { name = name; value = None }) -> sprintf "%s.%s=?" ty name
13521352
| Choice2Of2 l -> Literal.toString l)
13531353
yield sprintf "enum<%s>" (cases |> String.concat " | ")
13541354
for k, m in ru.discriminatedUnions |> Map.toSeq do
@@ -1357,7 +1357,7 @@ module ResolvedUnion =
13571357
]
13581358
cases |> String.concat " | "
13591359

1360-
let rec private getEnumFromUnion ctx (u: UnionType) : Set<Choice<EnumCase, Literal>> * UnionType =
1360+
let rec private getEnumFromUnion ctx (u: UnionType) : Set<Choice<Enum * EnumCase, Literal>> * UnionType =
13611361
let (|Dummy|) _ = []
13621362

13631363
let rec go t =
@@ -1373,10 +1373,10 @@ module ResolvedUnion =
13731373
let bindings = Type.createBindings fn loc a.typeParams tyargs
13741374
yield! go (a.target |> Type.substTypeVar bindings ())
13751375
| EnumName e ->
1376-
for c in e.cases do yield Choice1Of2 (Choice1Of2 c)
1376+
for c in e.cases do yield Choice1Of2 (Choice1Of2 (e, c))
13771377
| EnumCaseName (name, e) ->
13781378
match e.cases |> List.tryFind (fun c -> c.name = name) with
1379-
| Some c -> yield Choice1Of2 (Choice1Of2 c)
1379+
| Some c -> yield Choice1Of2 (Choice1Of2 (e, c))
13801380
| None -> yield Choice2Of2 t
13811381
| ClassName _ -> yield Choice2Of2 t
13821382
| _ -> ()

ts2ocaml.opam

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@ bug-reports: "https://github.com/ocsigen/ts2ocaml/issues"
1010
depends: [
1111
"dune" {>= "2.9"}
1212
"ocaml" {>= "4.08"}
13-
"gen_js_api"
13+
"gen_js_api" {>= "1.0.9"}
1414
"js_of_ocaml-compiler"
1515
]
16-
pin-depends: [
17-
[ "gen_js_api.dev" "git+https://github.com/LexiFi/gen_js_api.git" ]
18-
]
1916
dev-repo: "git+https://github.com/ocsigen/ts2ocaml.git"

0 commit comments

Comments
 (0)