Skip to content

Commit

Permalink
Add --readable-names
Browse files Browse the repository at this point in the history
Close #68.
  • Loading branch information
cannorin committed Jan 17, 2022
1 parent d75d016 commit b470255
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 34 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
- Add option `--human-readable-anonymous-interface-names` (or `--readable-names`) to try to use more readable names instead of `AnonymousInterfaceN`.

## [1.4.0-beta.2] - 2022-01-17
- Fix a bug which prevented ts2ocaml from generating anonymous interfaces when used with --simplify=named-interface-value

Expand Down
4 changes: 2 additions & 2 deletions build.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ module Test =
"safe", !! "node_modules/@types/scheduler/tracing.d.ts", [];
"full", !! "node_modules/csstype/index.d.ts", [];
"safe", !! "node_modules/@types/prop-types/index.d.ts", ["--rec-module=off"];
"full", !! "node_modules/@types/react/index.d.ts" ++ "node_modules/@types/react/global.d.ts", [];
"full", !! "node_modules/@types/react-modal/index.d.ts", [];
"full", !! "node_modules/@types/react/index.d.ts" ++ "node_modules/@types/react/global.d.ts", ["--readable-names"];
"full", !! "node_modules/@types/react-modal/index.d.ts", ["--readable-names"];

// "safe" package which depends on another "safe" package
"safe", !! "node_modules/@types/yargs-parser/index.d.ts", [];
Expand Down
55 changes: 29 additions & 26 deletions lib/Typer.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1071,15 +1071,39 @@ module Statement =
and typeFinder (state: {| origin: AnonymousInterfaceOrigin; namespace_: string list |}) ty =
let inline resultMany xs = Some [], state, xs
match ty with
| App (AAnonymousInterface i, _, _) ->
None, {| state with origin = AnonymousInterfaceOrigin.Empty |}, Seq.singleton (i, state)
| AnonymousInterface i ->
None, {| state with origin = AnonymousInterfaceOrigin.Empty |}, Seq.singleton (i, state)
| App (AAnonymousInterface i, _, _) | AnonymousInterface i ->
let inner =
let state = {| state with origin = AnonymousInterfaceOrigin.Empty |}
treatClassLike state (i.MapName(ignore))
None, {| state with origin = AnonymousInterfaceOrigin.Empty |}, Seq.append [i, state] inner
| Func (ft, tps, _) | NewableFunc (ft, tps, _) ->
treatFuncType state ft tps |> resultMany
| Union { types = types } | Intersection { types = types } ->
Some types, state, Seq.empty
| _ -> None, {| state with origin = AnonymousInterfaceOrigin.Empty |}, Seq.empty
and treatClassLike (state: {| origin: AnonymousInterfaceOrigin; namespace_: string list |}) (c: Class<unit>) =
seq {
for _, m in c.members do
match m with
| Method (name, ft, tps) ->
yield! treatFuncType {| state with origin = { state.origin with valueName = Some name } |} ft tps
| Newable (ft, tps) | Callable (ft, tps) -> yield! treatFuncType state ft tps
| Field (fl, _) | Getter fl | Setter fl -> yield! treatNamed state fl.name fl.value
| Indexer (ft, _) -> yield! treatFuncType state ft []
| SymbolIndexer (name, ft, _) ->
yield! treatFuncType {| state with origin = { state.origin with valueName = Some name } |} ft []
| Constructor ft ->
for arg in ft.args do
let ty, origin =
match arg with
| Choice1Of2 fl -> fl.value, { state.origin with argName = Some fl.name }
| Choice2Of2 t -> t, state.origin
yield! findTypes typeFinder {| state with origin = origin |} ty
| UnknownMember _ -> ()
for t in c.implements do
yield! findTypes typeFinder state t
yield! treatTypeParameters state c.typeParams
}

findStatements (fun currentNamespace state stmt ->
let inline result_ x = Some [], state, x
Expand All @@ -1099,28 +1123,7 @@ module Statement =
let typeName =
match c.name with Name n -> Some n | _ -> None
let state = {| state with namespace_ = currentNamespace; origin = { state.origin with typeName = typeName } |}
seq {
for _, m in c.members do
match m with
| Method (name, ft, tps) ->
yield! treatFuncType {| state with origin = { state.origin with valueName = Some name } |} ft tps
| Newable (ft, tps) | Callable (ft, tps) -> yield! treatFuncType state ft tps
| Field (fl, _) | Getter fl | Setter fl -> yield! treatNamed state fl.name fl.value
| Indexer (ft, _) -> yield! treatFuncType state ft []
| SymbolIndexer (name, ft, _) ->
yield! treatFuncType {| state with origin = { state.origin with valueName = Some name } |} ft []
| Constructor ft ->
for arg in ft.args do
let ty, origin =
match arg with
| Choice1Of2 fl -> fl.value, { state.origin with argName = Some fl.name }
| Choice2Of2 t -> t, state.origin
yield! findTypes typeFinder {| state with origin = origin |} ty
| UnknownMember _ -> ()
for t in c.implements do
yield! findTypes typeFinder state t
yield! treatTypeParameters state c.typeParams
} |> result_
treatClassLike state (c.MapName(ignore)) |> result_
| _ -> None, state.origin, Seq.empty
) AnonymousInterfaceOrigin.Empty stmts |> Set.ofSeq

Expand Down
9 changes: 9 additions & 0 deletions src/Targets/JsOfOCaml/Common.fs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ type Options =
abstract recModule: RecModule with get, set
abstract safeArity: FeatureFlag with get, set
abstract simplify: Simplify list with get, set
abstract humanReadableAnonymousInterfaceNames: bool with get, set

module Options =
open Fable.Core.JsInterop
Expand Down Expand Up @@ -223,6 +224,7 @@ module Options =
"safe-arity";
"rec-module";
"simplify";
"human-readable-anonymous-interface-names"
],
"Code Generator Options:")
.addChoice(
Expand All @@ -244,6 +246,13 @@ module Options =
descr=
sprintf "Turn on simplification features. Available features: %s"
(Simplify.Values |> Array.map string |> String.concat ", "))
.addFlag(
"human-readable-anonymous-interface-names",
(fun (o: Options) -> o.humanReadableAnonymousInterfaceNames),
descr="Try to use more readable names instead of AnonymousInterfaceN.",
defaultValue = false,
alias="readable-names"
)

.middleware(!^validate)

Expand Down
18 changes: 12 additions & 6 deletions src/Targets/JsOfOCaml/Writer.fs
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,18 @@ let literalToIdentifier (ctx: Context) (l: Literal) : text =
| LFloat l -> tprintf "n_%s" (formatNumber l)
| LBool true -> str "b_true" | LBool false -> str "b_false"

let anonymousInterfaceModuleName (info: AnonymousInterfaceInfo) =
sprintf "AnonymousInterface%d" info.id
let anonymousInterfaceModuleName (ctx: Context) (info: AnonymousInterfaceInfo) =
match info.origin.valueName, info.origin.argName with
| _, Some s | Some s, None when ctx.options.humanReadableAnonymousInterfaceNames ->
sprintf "%s%d" (Naming.toCase Naming.PascalCase s) info.id
| _, _ ->
sprintf "AnonymousInterface%d" info.id

let anonymousInterfaceToIdentifier (ctx: Context) (a: AnonymousInterface) : text =
match ctx |> Context.bindCurrentSourceInfo (fun i -> i.anonymousInterfacesMap |> Map.tryFind a) with
| Some i ->
if not ctx.options.recModule.IsOffOrDefault then
tprintf "%s.t" (anonymousInterfaceModuleName i)
tprintf "%s.t" (anonymousInterfaceModuleName ctx i)
else
tprintf "anonymous_interface_%d" i.id
| None -> failwithf "impossible_anonymousInterfaceToIdentifier(%s)" a.loc.AsString
Expand Down Expand Up @@ -576,7 +580,7 @@ module StructuredText =
|> Set.fold (fun state -> function
| KnownType.Ident fn when fn.source = ctx.currentSourceFile -> state |> WeakTrie.add fn.name
| KnownType.AnonymousInterface (_, i) ->
state |> WeakTrie.add (i.namespace_ @ [anonymousInterfaceModuleName i])
state |> WeakTrie.add (i.namespace_ @ [anonymousInterfaceModuleName ctx i])
| _ -> state
) WeakTrie.empty)
|> Option.defaultValue WeakTrie.empty
Expand Down Expand Up @@ -701,7 +705,9 @@ let rec emitMembers (emitType_: TypeEmitter) ctx (selfTy: Type) (ma: MemberAttri
| Indexer (ft, Mutable) ->
yield! emitMembers emitType_ ctx selfTy ma (Indexer (ft, ReadOnly))
yield! emitMembers emitType_ ctx selfTy ma (Indexer (ft, WriteOnly))
| SymbolIndexer _ -> ()
| SymbolIndexer (symbol, ft, _) ->
let ft = func ft |> emitType_ ctx
yield comment (tprintf "[Symbol.%s]: " symbol + ft) |> ScopeIndependent
| UnknownMember msgo ->
yield! comments ()
match msgo with
Expand Down Expand Up @@ -908,7 +914,7 @@ let rec emitClass flags overrideFunc (ctx: Context) (current: StructuredText) (c
Some (Type.appOpt (str "t") (ts |> List.map (_emitType _ctx)))
| _ -> None
ClassKind.AnonymousInterface {|
name = anonymousInterfaceModuleName i
name = anonymousInterfaceModuleName ctx i
orig = c.MapName(fun _ -> Anonymous)
|},
selfTy,
Expand Down

0 comments on commit b470255

Please sign in to comment.