Skip to content

Commit d12cfcc

Browse files
ncavealfonsogarciacaro
authored andcommitted
Type annotations update
1 parent 898b532 commit d12cfcc

File tree

7 files changed

+144
-241
lines changed

7 files changed

+144
-241
lines changed

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"name": "Run bench-compiler (.NET)",
4747
"program": "${workspaceFolder}/src/fable-standalone/test/bench-compiler/bin/Debug/netcoreapp3.1/bench-compiler.dll",
4848
// "args": ["${workspaceRoot}/tests/Main/Fable.Tests.fsproj", "out-tests"],
49-
"args": ["${workspaceRoot}/../fable-test/fable-test.fsproj", "out-test"],
49+
"args": ["${workspaceRoot}/../fable-test/fable-test.fsproj", "out-test", "--typescript"],
5050
"cwd": "${workspaceFolder}/src/fable-standalone/test/bench-compiler"
5151
},
5252
{

src/Fable.Transforms/AST/AST.Babel.fs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,12 +1112,11 @@ type ClassProperty(key, ?value, ?computed_, ?``static``, ?optional, ?typeAnnotat
11121112
printer.PrintOptional(typeAnnotation)
11131113
printer.PrintOptional(": ", value)
11141114

1115-
type ClassImplements(id, ?typeParameters, ?loc) =
1115+
type ClassImplements(id, ?typeParameters) =
11161116
member _.Id: Identifier = id
11171117
member _.TypeParameters: TypeParameterInstantiation option = typeParameters
11181118
interface Expression with
11191119
member _.Print(printer) =
1120-
printer.Print(" implements ", ?loc=loc)
11211120
printer.Print(id)
11221121
printer.PrintOptional(typeParameters)
11231122

src/Fable.Transforms/Fable2Babel.fs

Lines changed: 51 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -347,21 +347,6 @@ module Annotation =
347347
GenericTypeAnnotation(Identifier name, ?typeParameters=typeParamInst) :> TypeAnnotationInfo
348348
|> TypeAnnotation |> Some
349349

350-
let makeInterfaceDecl (com: IBabelCompiler) ctx (ent: Fable.Entity) (entName: string) (baseExpr: Expression option) =
351-
let genTypeParams = getEntityGenParams ent
352-
let newTypeParams = Set.difference genTypeParams ctx.ScopedTypeParams
353-
let ctx = { ctx with ScopedTypeParams = Set.union ctx.ScopedTypeParams newTypeParams }
354-
let attached = Util.getEntityExplicitInterfaceMembers com ctx ent
355-
let extends =
356-
Util.getInterfaceExtends com ctx ent
357-
|> Seq.toArray
358-
|> function [||] -> None | e -> Some e
359-
// Type declaration merging only works well with class declarations, not class expressions
360-
let id = Identifier(entName)
361-
let body = ObjectTypeAnnotation([| yield! attached |])
362-
let typeParamDecl = genTypeParams |> makeTypeParamDecl
363-
InterfaceDeclaration(id, body, ?extends_=extends, ?typeParameters=typeParamDecl)
364-
365350
let typeAnnotation com ctx typ: TypeAnnotationInfo =
366351
match typ with
367352
| Fable.MetaType -> upcast AnyTypeAnnotation()
@@ -1214,7 +1199,7 @@ module Util =
12141199

12151200
let transformBindingAsStatements (com: IBabelCompiler) ctx (var: Fable.Ident) (value: Fable.Expr) =
12161201
if isJsStatement ctx false value then
1217-
let var = typedIdent com ctx var
1202+
let var = ident var
12181203
let decl = VariableDeclaration(var) :> Statement
12191204
let body = com.TransformAsStatements(ctx, Some(Assign var), value)
12201205
Array.append [|decl|] body
@@ -1645,7 +1630,7 @@ module Util =
16451630
let tailcallChance =
16461631
Option.map (fun name ->
16471632
NamedTailCallOpportunity(com, ctx, name, args) :> ITailCallOpportunity) name
1648-
let args = discardUnitArg args |> List.map (typedIdent com ctx)
1633+
let args = discardUnitArg args
16491634
let declaredVars = ResizeArray()
16501635
let mutable isTailCallOptimized = false
16511636
let ctx =
@@ -1663,21 +1648,21 @@ module Util =
16631648
match isTailCallOptimized, tailcallChance with
16641649
| true, Some tc ->
16651650
// Replace args, see NamedTailCallOpportunity constructor
1666-
let args, body =
1667-
let tcArgs =
1668-
tc.Args
1669-
|> List.map (fun arg -> Identifier(arg))
1670-
let varDecls =
1671-
tcArgs
1672-
|> List.map (fun arg -> Some (arg :> Expression))
1673-
|> List.zip args
1674-
|> multiVarDeclaration Const
1675-
tcArgs, BlockStatement(Array.append [|varDecls|] body.Body)
1651+
let args' =
1652+
List.zip args tc.Args
1653+
|> List.map (fun (id, tcArg) ->
1654+
makeTypedIdent id.Type tcArg |> typedIdent com ctx)
1655+
let varDecls =
1656+
List.zip args tc.Args
1657+
|> List.map (fun (id, tcArg) ->
1658+
id |> typedIdent com ctx, Some (Identifier(tcArg) :> Expression))
1659+
|> multiVarDeclaration Const
1660+
let body = BlockStatement(Array.append [|varDecls|] body.Body)
16761661
// Make sure we don't get trapped in an infinite loop, see #1624
16771662
let body = BlockStatement(Array.append body.Body [|BreakStatement()|])
1678-
args, LabeledStatement(Identifier tc.Label, WhileStatement(BooleanLiteral true, body))
1663+
args', LabeledStatement(Identifier tc.Label, WhileStatement(BooleanLiteral true, body))
16791664
:> Statement |> Array.singleton |> BlockStatement
1680-
| _ -> args, body
1665+
| _ -> args |> List.map (typedIdent com ctx), body
16811666
let body =
16821667
if declaredVars.Count = 0 then body
16831668
else
@@ -1719,121 +1704,26 @@ module Util =
17191704
else
17201705
None
17211706

1722-
let getInterfaceExtends com ctx (ent: Fable.Entity) =
1707+
let getClassImplements com ctx (ent: Fable.Entity) =
17231708
let mkNative genArgs typeName =
17241709
let id = Identifier(typeName)
17251710
let typeParamInst = makeGenTypeParamInst com ctx genArgs
1726-
InterfaceExtends(id, ?typeParameters=typeParamInst) |> Some
1711+
ClassImplements(id, ?typeParameters=typeParamInst) |> Some
17271712
let mkImport genArgs moduleName typeName =
17281713
let id = makeImportTypeId com ctx moduleName typeName
17291714
let typeParamInst = makeGenTypeParamInst com ctx genArgs
1730-
InterfaceExtends(id, ?typeParameters=typeParamInst) |> Some
1731-
1732-
// let isIEquatable = FSharp2Fable.Util.hasInterface Types.iequatable ent
1733-
// let isIComparable = FSharp2Fable.Util.hasInterface Types.icomparable ent
1734-
1715+
ClassImplements(id, ?typeParameters=typeParamInst) |> Some
17351716
ent.AllInterfaces |> Seq.choose (fun ifc ->
17361717
match ifc.Definition.FullName with
1737-
| Types.ienumerableGeneric ->
1738-
mkImport ifc.GenericArgs "Seq" "IEnumerable"
1739-
| Types.ienumeratorGeneric ->
1740-
mkImport ifc.GenericArgs "Seq" "IEnumerator"
1741-
| Types.iequatable ->
1742-
mkImport [Fable.Any] "Util" "IEquatable"
1743-
| Types.icomparable ->
1744-
mkImport [Fable.Any] "Util" "IComparable"
1745-
// | Types.iequatableGeneric when not isIEquatable ->
1746-
// mkImport ifc.GenericArgs "Util" "IEquatable"
1747-
// | Types.icomparableGeneric when not isIComparable ->
1748-
// mkImport ifc.GenericArgs "Util" "IComparable"
1749-
| Types.comparer ->
1750-
mkImport ifc.GenericArgs "Util" "IComparer"
1751-
// this is not needed, as it's already included in every object
1752-
// | Types.equalityComparer ->
1753-
// mkImport ifc.GenericArgs "Util" "IEqualityComparer"
1754-
| Types.idisposable ->
1755-
mkImport [] "Util" "IDisposable"
1756-
| Types.icollectionGeneric ->
1757-
mkImport ifc.GenericArgs "Util" "ICollection"
1758-
| "Fable.Collections.IMutableSet`1" ->
1759-
mkImport ifc.GenericArgs "Util" "IMutableSet"
1760-
| "Fable.Collections.IMutableMap`2" ->
1761-
mkImport ifc.GenericArgs "Util" "IMutableMap"
1762-
// TODO: add other interfaces
1718+
| "Fable.Collections.IMutableSet`1" -> mkNative ifc.GenericArgs "Set"
1719+
| "Fable.Collections.IMutableMap`2" -> mkNative ifc.GenericArgs "Map"
17631720
| _ -> None
17641721
)
17651722

1766-
// must match the above list (with the exception of IEqualityComparer)
1767-
let alreadyDeclaredInterfaces =
1768-
set [
1769-
Types.ienumerableGeneric
1770-
Types.ienumeratorGeneric
1771-
Types.iequatable
1772-
Types.icomparable
1773-
// Types.iequatableGeneric
1774-
// Types.icomparableGeneric
1775-
Types.comparer
1776-
Types.equalityComparer
1777-
Types.idisposable
1778-
Types.icollectionGeneric
1779-
"Fable.Collections.IMutableSet`1"
1780-
"Fable.Collections.IMutableMap`2"
1781-
]
1782-
1783-
let isOtherInterfaceMember (memb: Fable.MemberFunctionOrValue) =
1784-
let isInterface, fullName =
1785-
if memb.IsExplicitInterfaceImplementation then
1786-
true, memb.CompiledName.Replace("-",".")
1787-
else
1788-
let ent = memb.ApparentEnclosingEntity
1789-
ent.IsInterface, memb.FullName
1790-
let lastDot = fullName.LastIndexOf(".")
1791-
let entName = if lastDot < 0 then fullName else fullName.Substring(0, lastDot)
1792-
isInterface && not (alreadyDeclaredInterfaces.Contains entName)
1793-
1794-
let getEntityExplicitInterfaceMembers com ctx (ent: Fable.Entity) =
1795-
ent.MembersFunctionsAndValues
1796-
|> Seq.filter isOtherInterfaceMember
1797-
|> Seq.map (fun memb ->
1798-
let args =
1799-
List.concat memb.CurriedParameterGroups
1800-
|> List.mapi (fun i p ->
1801-
let name =
1802-
defaultArg p.Name ("arg" + (string i))
1803-
|> Naming.sanitizeIdentForbiddenChars |> Naming.checkJsKeywords
1804-
name, p.Type
1805-
)
1806-
let argTypes = args |> List.map snd
1807-
let retType = memb.ReturnParameter.Type
1808-
let genTypeParams = getGenericTypeParams (argTypes @ [retType])
1809-
let newTypeParams = Set.difference genTypeParams ctx.ScopedTypeParams
1810-
let ctx = { ctx with ScopedTypeParams = Set.union ctx.ScopedTypeParams newTypeParams }
1811-
let funcArgs =
1812-
args
1813-
|> Seq.map (fun (name, typ) ->
1814-
let typeInfo = typeAnnotation com ctx typ
1815-
FunctionTypeParam(Identifier(name), typeInfo)
1816-
) |> Seq.toArray
1817-
let returnType = retType |> typeAnnotation com ctx
1818-
let typeParamDecl = makeTypeParamDecl newTypeParams
1819-
let funcTypeInfo =
1820-
FunctionTypeAnnotation(funcArgs, returnType, ?typeParameters=typeParamDecl)
1821-
:> TypeAnnotationInfo
1822-
// TODO!!! This should be the compiled name if the interface is not mangled
1823-
let name = memb.DisplayName
1824-
let membId = Identifier(name)
1825-
ObjectTypeProperty(membId, funcTypeInfo)
1826-
)
1827-
|> Seq.toArray
1828-
1829-
let getEntityFieldsAsProps (com: IBabelCompiler) ctx (ent: Fable.Entity) =
1830-
ent.FSharpFields
1831-
|> Seq.map (fun field ->
1832-
let id, computed = memberFromName field.Name
1833-
let ta = typeAnnotation com ctx field.FieldType
1834-
let isStatic = if field.IsStatic then Some true else None
1835-
ObjectTypeProperty(id, ta, computed_=computed, ?``static``=isStatic))
1836-
|> Seq.toArray
1723+
let getUnionFieldsAsIdents (com: IBabelCompiler) ctx (ent: Fable.Entity) =
1724+
let tagId = makeTypedIdent (Fable.Number Int32) "tag"
1725+
let fieldsId = makeTypedIdent (Fable.Array Fable.Any) "fields"
1726+
[| tagId; fieldsId |]
18371727

18381728
let getEntityFieldsAsIdents com (ent: Fable.Entity) =
18391729
ent.FSharpFields
@@ -1844,9 +1734,30 @@ module Util =
18441734
id)
18451735
|> Seq.toArray
18461736

1737+
let getEntityFieldsAsProps (com: IBabelCompiler) ctx (ent: Fable.Entity) =
1738+
if (ent.IsFSharpUnion) then
1739+
getUnionFieldsAsIdents com ctx ent
1740+
|> Array.map (fun id ->
1741+
let prop = ident id
1742+
let ta = typeAnnotation com ctx id.Type
1743+
ObjectTypeProperty(prop, ta))
1744+
else
1745+
ent.FSharpFields
1746+
|> Seq.map (fun field ->
1747+
let prop, computed = memberFromName field.Name
1748+
let ta = typeAnnotation com ctx field.FieldType
1749+
let isStatic = if field.IsStatic then Some true else None
1750+
ObjectTypeProperty(prop, ta, computed_=computed, ?``static``=isStatic))
1751+
|> Seq.toArray
1752+
18471753
let declareClassType (com: IBabelCompiler) ctx (ent: Fable.Entity) entName (consArgs: Pattern[]) (consBody: BlockStatement) (baseExpr: Expression option) classMembers =
18481754
let consId = Identifier "constructor"
18491755
let typeParamDecl = makeEntityTypeParamDecl com ctx ent
1756+
let implements =
1757+
if com.Options.Typescript then
1758+
let implements = Util.getClassImplements com ctx ent |> Seq.toArray
1759+
if Array.isEmpty implements then None else Some implements
1760+
else None
18501761
let consBody =
18511762
if ent.IsFSharpExceptionDeclaration then
18521763
let super = callSuperConstructor None [] |> ExpressionStatement :> Statement
@@ -1862,13 +1773,13 @@ module Util =
18621773
else Array.empty
18631774
let classMembers = Array.append [| classCons |] classMembers
18641775
let classBody = ClassBody([| yield! classFields; yield! classMembers |])
1865-
let classExpr = ClassExpression(classBody, ?superClass=baseExpr, ?typeParameters=typeParamDecl)
1776+
let classExpr = ClassExpression(classBody, ?superClass=baseExpr, ?typeParameters=typeParamDecl, ?implements=implements)
18661777
classExpr |> declareModuleMember ent.IsPublic entName false
18671778

18681779
let declareType (com: IBabelCompiler) ctx (ent: Fable.Entity) entName (consArgs: Pattern[]) (consBody: BlockStatement) baseExpr classMembers: ModuleDeclaration list =
18691780
let typeDeclaration = declareClassType com ctx ent entName consArgs consBody baseExpr classMembers
18701781
let reflectionDeclaration =
1871-
let genArgs = Array.init (ent.GenericParameters.Length) (fun i -> "gen" + string i |> makeIdent |> typedIdent com ctx)
1782+
let genArgs = Array.init (ent.GenericParameters.Length) (fun i -> "gen" + string i |> makeIdent |> ident)
18721783
let body = transformReflectionInfo com ctx None ent (Array.map (fun x -> x :> _) genArgs)
18731784
let returnType =
18741785
if com.Options.Typescript then
@@ -1878,12 +1789,7 @@ module Util =
18781789
let args = genArgs |> Array.map (fun x -> x :> Pattern)
18791790
makeFunctionExpression None (args, body, returnType, None)
18801791
|> declareModuleMember ent.IsPublic (entName + Naming.reflectionSuffix) false
1881-
if com.Options.Typescript then
1882-
let interfaceDecl = makeInterfaceDecl com ctx ent entName baseExpr
1883-
let interfaceDeclaration = ExportNamedDeclaration(interfaceDecl) :> ModuleDeclaration
1884-
[interfaceDeclaration; typeDeclaration; reflectionDeclaration]
1885-
else
1886-
[typeDeclaration; reflectionDeclaration]
1792+
[typeDeclaration; reflectionDeclaration]
18871793

18881794
let transformModuleFunction (com: IBabelCompiler) ctx (info: Fable.MemberInfo) (membName: string) args body =
18891795
let args, body, returnType, typeParamDecl =
@@ -1930,14 +1836,12 @@ module Util =
19301836
|]
19311837

19321838
let transformUnion (com: IBabelCompiler) ctx (ent: Fable.Entity) (entName: string) classMembers =
1933-
1934-
let tagId = makeTypedIdent (Fable.Number Int32) "tag"
1935-
let fieldsId = makeTypedIdent (Fable.Array Fable.Any) "fields"
1839+
let fieldIds = getUnionFieldsAsIdents com ctx ent
19361840
let args =
1937-
[| typedIdent com ctx tagId :> Pattern
1938-
typedIdent com ctx fieldsId |> restElement |]
1841+
[| typedIdent com ctx fieldIds.[0] :> Pattern
1842+
typedIdent com ctx fieldIds.[1] |> restElement |]
19391843
let body =
1940-
[| tagId; fieldsId |]
1844+
fieldIds
19411845
|> Array.map (fun id ->
19421846
let left = get None thisExpr id.Name
19431847
let right =

src/fable-library/Option.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,13 @@ export function value<T>(x: Option<T>) {
6868
}
6969
}
7070

71-
export function ofNullable<T>(x: T|null): Option<T> {
71+
export function ofNullable<T>(x: T | null): Option<T> {
7272
// This will fail with unit probably, an alternative would be:
7373
// return x === null ? undefined : (x === undefined ? new Some(x) : x);
7474
return x == null ? undefined : x;
7575
}
7676

77-
export function toNullable<T>(x: Option<T>): T|null {
77+
export function toNullable<T>(x: Option<T>): T | null {
7878
return x == null ? null : value(x);
7979
}
8080

0 commit comments

Comments
 (0)