Skip to content

Commit

Permalink
Updated fable-library types
Browse files Browse the repository at this point in the history
  • Loading branch information
ncave authored and alfonsogarciacaro committed Jun 9, 2020
1 parent 8b8e010 commit 2d0d3ba
Show file tree
Hide file tree
Showing 17 changed files with 130 additions and 51 deletions.
12 changes: 12 additions & 0 deletions build.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,17 @@ let buildLibrary() =
buildTypescript "src/fable-library"
buildSplitter "src/fable-library"

let buildLibraryTs() =
let projectDir = "src/fable-library"
let buildDirTs = "build/fable-library-ts"
let buildDirJs = "build/fable-library-js"
cleanDirs [buildDirTs; buildDirJs]
buildSplitterWithArgs projectDir ("--typescript --classTypes --outDir " + buildDirTs)
// TODO: cleanDirs [buildDirTs </> "fable-library"]
// TODO: copy *.ts/*.js from projectDir to buildDir
runInDir buildDirTs "npx tsc --init --target es2020 --module es2020 --allowJs"
runInDir buildDirTs ("npx tsc --outDir ../../" + buildDirJs)

let quicktest additionalCommands =
cleanDirs ["build/fable-library"]
concurrently [|
Expand Down Expand Up @@ -303,6 +314,7 @@ match argsLower with
|||> sprintf "nodemon --watch src/quicktest/bin/Quicktest.js --exec 'source-map-visualization --sm=\"%s;%s;%s\"'"
|> List.singleton |> quicktest
| ("fable-library"|"library")::_ -> buildLibrary()
| ("fable-library-ts"|"library-ts")::_ -> buildLibraryTs()
| ("fable-compiler"|"compiler")::_ -> buildCompiler()
| ("fable-compiler-js"|"compiler-js")::_ -> buildCompilerJs()
| ("fable-splitter"|"splitter")::_ -> buildFableSplitter()
Expand Down
3 changes: 2 additions & 1 deletion src/Fable.Transforms/AST/AST.Babel.fs
Original file line number Diff line number Diff line change
Expand Up @@ -732,14 +732,15 @@ type GenericTypeAnnotation(id, ?typeParameters) =
member __.Id: Identifier = id
member __.TypeParameters: TypeParameterInstantiation option = typeParameters

type ObjectTypeProperty(key, value, ?kind, ?``static``, ?optional, ?proto) =
type ObjectTypeProperty(key, value, ?kind, ?``static``, ?optional, ?proto, ?method) =
inherit Node("ObjectTypeProperty")
member __.Key: U2<Identifier, StringLiteral> = key
member __.Value: TypeAnnotationInfo = value
member __.Kind: string option = kind
member __.Static: bool option = ``static``
member __.Optional: bool option = optional
member __.Proto: bool option = proto
member __.Method: bool option = method

type ObjectTypeIndexer(key, value, ?id, ?``static``) =
inherit Node("ObjectTypeIndexer")
Expand Down
15 changes: 11 additions & 4 deletions src/Fable.Transforms/FSharp2Fable.Util.fs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,13 @@ module Helpers =
getMemberMangledName com false memb
||> Naming.buildNameWithoutSanitation

let getMemberFullName (memb: FSharpMemberOrFunctionOrValue) =
if memb.IsExplicitInterfaceImplementation
then true, memb.CompiledName.Replace("-",".")
else
let ent = memb.ApparentEnclosingEntity
ent.IsInterface, memb.FullName

/// TODO: Latest FCS seems to add get_/set_ to DisplayName. Bug or feature?
let getMemberDisplayName (memb: FSharpMemberOrFunctionOrValue) =
Naming.removeGetSetPrefix memb.DisplayName
Expand Down Expand Up @@ -667,14 +674,14 @@ module TypeHelpers =
| _ -> ()
}

let isAttachedMember (memb: FSharpMemberOrFunctionOrValue) =
memb.IsOverrideOrExplicitInterfaceImplementation

let isIgnoredAttachedMember (memb: FSharpMemberOrFunctionOrValue) =
memb.IsCompilerGenerated || Naming.ignoredAttachedMembers.Contains memb.CompiledName

let isNotIgnoredAttachedMember (memb: FSharpMemberOrFunctionOrValue) =
memb.IsOverrideOrExplicitInterfaceImplementation && not (isIgnoredAttachedMember memb)

let getOverrideOrExplicitInterfaceMembers (tdef: FSharpEntity) =
tdef.TryGetMembersFunctionsAndValues |> Seq.filter isNotIgnoredAttachedMember
isAttachedMember memb && not (isIgnoredAttachedMember memb)

let getArgTypes com (memb: FSharpMemberOrFunctionOrValue) =
// FSharpParameters don't contain the `this` arg
Expand Down
2 changes: 1 addition & 1 deletion src/Fable.Transforms/FSharp2Fable.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1015,7 +1015,7 @@ let private transformMemberDecl (com: FableCompiler) (ctx: Context) (memb: FShar
else []
elif memb.IsImplicitConstructor
then transformImplicitConstructor com ctx memb args body
elif memb.IsOverrideOrExplicitInterfaceImplementation then
elif isAttachedMember memb then
if isIgnoredAttachedMember memb then []
else transformAttachedMember com ctx memb args body
else transformMemberFunctionOrValue com ctx memb args body
Expand Down
92 changes: 70 additions & 22 deletions src/Fable.Transforms/Fable2Babel.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1726,7 +1726,7 @@ module Util =
| Fable.DeclaredType(ent, genArgs) ->
match ent.TryFullName with
| Some Types.ienumerableGeneric ->
mkNative genArgs "Iterable"
mkImport genArgs "Seq" "IEnumerable"
| Some Types.ienumeratorGeneric ->
mkImport genArgs "Seq" "IEnumerator"
| Some Types.iequatable ->
Expand All @@ -1737,8 +1737,9 @@ module Util =
// mkImport genArgs "Util" "IEquatable"
// | Some Types.icomparableGeneric when not isIComparable ->
// mkImport genArgs "Util" "IComparable"
// | Some Types.comparer ->
// mkImport genArgs "Util" "IComparer"
| Some Types.comparer ->
mkImport genArgs "Util" "IComparer"
// this is not needed, as it's already included in every object
// | Some Types.equalityComparer ->
// mkImport genArgs "Util" "IEqualityComparer"
| Some Types.idisposable ->
Expand All @@ -1754,28 +1755,66 @@ module Util =
| _ -> None
)

let getGenericTypeAnnotation com ctx name genParams =
let id = Identifier(name)
let typeParamInst = makeTypeParamInst genParams
GenericTypeAnnotation(id, ?typeParameters=typeParamInst) :> TypeAnnotationInfo
|> TypeAnnotation |> Some

let getEntityOverrideMembers com ctx (ent: FSharpEntity) =
FSharp2Fable.TypeHelpers.getOverrideOrExplicitInterfaceMembers ent
// must match the above list (with the exception of IEqualityComparer)
let alreadyDeclaredInterfaces =
set [
Types.ienumerableGeneric
Types.ienumeratorGeneric
Types.iequatable
Types.icomparable
// Types.iequatableGeneric
// Types.icomparableGeneric
Types.comparer
Types.equalityComparer
Types.idisposable
Types.icollectionGeneric
"Fable.Collections.IMutableSet`1"
"Fable.Collections.IMutableMap`2"
]

let isOtherInterfaceMember (memb: FSharpMemberOrFunctionOrValue) =
let isInterface, fullName = FSharp2Fable.Helpers.getMemberFullName memb
let lastDot = fullName.LastIndexOf(".")
let entName = if lastDot < 0 then fullName else fullName.Substring(0, lastDot)
isInterface
&& FSharp2Fable.TypeHelpers.isNotIgnoredAttachedMember memb
&& not (alreadyDeclaredInterfaces.Contains entName)

let getEntityExplicitInterfaceMembers com ctx (ent: FSharpEntity) =
let ctxTypeArgs = Map.empty
ent.TryGetMembersFunctionsAndValues
|> Seq.filter isOtherInterfaceMember
|> Seq.map (fun memb ->
let args =
Seq.concat memb.CurriedParameterGroups
|> Seq.mapi (fun i p ->
let name =
defaultArg p.Name ("arg" + (string i))
|> Naming.sanitizeIdentForbiddenChars |> Naming.checkJsKeywords
let typ = FSharp2Fable.TypeHelpers.makeType com Map.empty p.Type
let ta = typeAnnotation com ctx typ |> TypeAnnotation |> Some
Identifier(name, ?typeAnnotation=ta) |> toPattern)
|> Seq.toArray
let membId = Identifier(memb.DisplayName)
let body = BlockStatement [||]
ClassMethod(ClassFunction, membId, args, body, false, false)
let typ = FSharp2Fable.TypeHelpers.makeType com ctxTypeArgs p.Type
name, typ
)
let argTypes = args |> Seq.map snd |> Seq.toList
let retType =
memb.ReturnParameter.Type
|> FSharp2Fable.TypeHelpers.makeType com ctxTypeArgs
let genTypeParams = getGenericTypeParams (argTypes @ [retType])
let newTypeParams = Set.difference genTypeParams ctx.ScopedTypeParams
let ctx = { ctx with ScopedTypeParams = Set.union ctx.ScopedTypeParams newTypeParams }
let funcArgs =
args
|> Seq.map (fun (name, typ) ->
let typeInfo = typeAnnotation com ctx typ
FunctionTypeParam(Identifier(name), typeInfo)
) |> Seq.toArray
let returnType = retType |> typeAnnotation com ctx
let typeParamDecl = makeTypeParamDecl newTypeParams
let funcTypeInfo =
FunctionTypeAnnotation(funcArgs, returnType, ?typeParameters=typeParamDecl)
:> TypeAnnotationInfo
let name = FSharp2Fable.Helpers.getMemberDisplayName memb
let membId = Identifier(name) |> U2.Case1
ObjectTypeProperty(membId, funcTypeInfo)
)
|> Seq.toArray

Expand Down Expand Up @@ -1803,12 +1842,21 @@ module Util =
id)
|> Seq.toArray

let getGenericTypeAnnotation com ctx name genParams =
let id = Identifier(name)
let typeParamInst = makeTypeParamInst genParams
GenericTypeAnnotation(id, ?typeParameters=typeParamInst) :> TypeAnnotationInfo
|> TypeAnnotation |> Some

let makeInterfaceDecl (com: IBabelCompiler) ctx r (ent: FSharpEntity) name (baseExpr: Expression option) =
let properties =
let genTypeParams = getEntityGenParams ent
let newTypeParams = Set.difference genTypeParams ctx.ScopedTypeParams
let ctx = { ctx with ScopedTypeParams = Set.union ctx.ScopedTypeParams newTypeParams }
let fields =
if not (com.Options.classTypes)
then getEntityFieldsAsProps com ctx ent
else Array.empty
// let overrides = getEntityOverrideMembers com ctx ent |> Array.map U2.Case1 //TODO:
let attached = getEntityExplicitInterfaceMembers com ctx ent
let baseExt =
match baseExpr with
| Some expr when not (com.Options.classTypes) ->
Expand All @@ -1828,8 +1876,8 @@ module Util =
// so we're adding a prefix to the interface name, which will be removed after transpiling.
let prefix = if com.Options.classTypes then "$INTERFACE_DECL_PREFIX$_" else ""
let id = Identifier(prefix + name)
let body = ObjectTypeAnnotation(properties)
let typeParamDecl = getEntityGenParams ent |> makeTypeParamDecl
let body = ObjectTypeAnnotation([| yield! fields; yield! attached |])
let typeParamDecl = genTypeParams |> makeTypeParamDecl
InterfaceDeclaration(id, body, ?extends_=extends, ?typeParameters=typeParamDecl, ?loc=r)

let declareObjectType (com: IBabelCompiler) ctx r isPublic (ent: FSharpEntity) name (consArgs: Pattern[]) (consBody: BlockStatement) (baseExpr: Expression option) =
Expand Down
3 changes: 0 additions & 3 deletions src/Fable.Transforms/Global/Prelude.fs
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,6 @@ module Naming =
"System-Collections-IEnumerable-GetEnumerator"
"System-IEquatable`1-Equals"
"System-IComparable`1-CompareTo"
// "System-Collections-Generic-IComparer`1-Compare"
// "System-Collections-Generic-IEqualityComparer`1-Equals"
// "System-Collections-Generic-IEqualityComparer`1-GetHashCode"
]

let umdModules =
Expand Down
3 changes: 2 additions & 1 deletion src/fable-compiler-js/src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,10 @@ function getJsImport(sourcePath, importPath, outPath, projDir, outDir, libDir, b
if (importPath.match(FSHARP_EXT)) {
relPath = relPath.replace(FSHARP_EXT, options.typescript ? "" : ".js");
} else {
relPath = relPath.match(JAVASCRIPT_EXT) || options.typescript ? relPath : relPath + ".js";
relPath = (relPath.match(JAVASCRIPT_EXT) || options.typescript) ? relPath : relPath + ".js";
absPath = absPath.match(JAVASCRIPT_EXT) ? absPath : absPath + ".js";
outPath = Path.resolve(Path.dirname(outPath), relPath);
outPath = outPath.match(JAVASCRIPT_EXT) ? outPath : outPath + ".js";
// if not already done, transform and save javascript imports
if (!uniquePaths.has(outPath) || uniquePaths.get(outPath) !== absPath) {
outPath = ensureUniquePath(absPath, outPath);
Expand Down
5 changes: 3 additions & 2 deletions src/fable-library/Async.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ import { choice1Of2, choice2Of2 } from "./Option";
import { map } from "./Seq";

// Implemented just for type references
export default class Async<_T> {
}
export class Async<_T> { }

function emptyContinuation<T>(_x: T) {
// NOP
Expand Down Expand Up @@ -147,3 +146,5 @@ export function startAsPromise<T>(computation: IAsync<T>, cancellationToken?: Ca
startWithContinuations(computation, resolve, reject, reject,
cancellationToken ? cancellationToken : defaultCancellationToken));
}

export default Async;
4 changes: 3 additions & 1 deletion src/fable-library/Date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export function toString(date: IDateTime | IDateTimeOffset, format?: string, _pr
: dateToStringWithKind(date, format);
}

export default function DateTime(value: number, kind?: DateKind) {
export function DateTime(value: number, kind?: DateKind) {
const d = new Date(value) as IDateTime;
d.kind = (kind == null ? DateKind.Unspecified : kind) | 0;
return d;
Expand Down Expand Up @@ -449,3 +449,5 @@ export function isDaylightSavingTime(x: IDateTime) {
function isDST(janOffset: number, julOffset: number, tOffset: number) {
return Math.min(janOffset, julOffset) === tOffset;
}

export default DateTime;
4 changes: 3 additions & 1 deletion src/fable-library/Event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export interface IEvent<T> extends IObservable<T>, IDelegateEvent<T> {
Trigger(x: T): void;
}

export default class Event<T> implements IEvent<T> {
export class Event<T> implements IEvent<T> {
public delegates: Delegate<T>[];
private _subscriber?: (o: IObserver<T>) => IDisposable;
private _dotnetDelegates?: Map<DotNetDelegate<T>, Delegate<T>>;
Expand Down Expand Up @@ -216,3 +216,5 @@ export function split<T, U1, U2>(splitter: (x: T) => Choice<U1, U2>, sourceEvent
choose((v) => tryValueIfChoice2Of2(splitter(v)), sourceEvent),
];
}

export default Event;
4 changes: 3 additions & 1 deletion src/fable-library/MailboxProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export interface AsyncReplyChannel<Reply> {
reply: (r: Reply) => void;
}

export default class MailboxProcessor<Msg> {
export class MailboxProcessor<Msg> {
public body: MailboxBody<Msg>;
public cancellationToken: CancellationToken;
public messages: MailboxQueue<Msg>;
Expand Down Expand Up @@ -121,3 +121,5 @@ export function start<Msg>(body: MailboxBody<Msg>, cancellationToken?: Cancellat
startInstance(mbox);
return mbox;
}

export default MailboxProcessor;
2 changes: 1 addition & 1 deletion src/fable-library/Seq.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export interface IEnumerator<T> {
Reset(): void;
}

export interface IEnumerable<T> {
export interface IEnumerable<T> extends Iterable<T> {
GetEnumerator(): IEnumerator<T>;
}

Expand Down
4 changes: 3 additions & 1 deletion src/fable-library/Timer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Event from "./Event";
import { IDisposable } from "./Util";

export default class Timer implements IDisposable {
export class Timer implements IDisposable {
public Interval: number;
public AutoReset: boolean;

Expand Down Expand Up @@ -76,3 +76,5 @@ export default class Timer implements IDisposable {
this.Enabled = false;
}
}

export default Timer;
8 changes: 4 additions & 4 deletions src/fable-library/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ export class SystemObject implements IEquatable<any> {
return "{" + Object.entries(this).map(([k, v]) => k + " = " + String(v)).join(";\n ") + "}";
}

public GetHashCode() {
return identityHash(this);
public GetHashCode(x?: any) {
return identityHash(x ?? this);
}

public Equals(other: any) {
return this === other;
public Equals(x: any, y?: any) {
return x === (y ?? this);
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/fable-library/Uri.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export const enum UriKind {
Relative = 2,
}

export default class Uri {
export class Uri {
private url?: string | URL;
private kind?: UriKind;

Expand Down Expand Up @@ -112,3 +112,5 @@ export default class Uri {
return this.parseUrl().hash;
}
}

export default Uri;
13 changes: 7 additions & 6 deletions src/fable-standalone/test/bench-compiler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,23 @@
"terser-bundle": "npm run terser -- dist/bundle.js -o dist/bundle.min.js --mangle --compress",
"webpack-bundle": "npm run webpack -- -p --entry ./out-node/app.js --output ./dist/bundle.min.js --target node",

"prebuild-lib-dotnet": "if exist out-lib (rmdir /s /q out-lib)",
"build-lib-dotnet": "dotnet run -c Release ../../../fable-library/Fable.Library.fsproj out-lib --typescript && npm run build-lib-transform",
"build-lib-transform": "node transform ../../../fable-library/Fable.Library.fsproj out-lib ../../../../build/fable-library --typescript",
"prebuild-lib-dotnet-ts": "if exist out-lib (rmdir /s /q out-lib)",
"build-lib-dotnet-ts": "dotnet run -c Release ../../../fable-library/Fable.Library.fsproj out-lib --classTypes --typescript && npm run build-lib-transform -- --typescript",
"build-lib-transform": "node transform ../../../fable-library/Fable.Library.fsproj out-lib ../../../../build/fable-library",
"postbuild-lib-transform": "rmdir /s /q out-lib\\fable-library && xcopy /s /y ..\\..\\..\\fable-library\\*.ts out-lib\\",
"tsc-lib-init": "npm run tsc -- --init --target es2020 --module es2020 --allowJs",
"tsc-lib": "npm run tsc -- -p ./out-lib --outDir ./out-lib-js",

"build-test-node": "node out-node/app.js ../../../../../fable-test/fable-test.fsproj out-test --classTypes --typescript && npm run build-test-transform",
"build-test-dotnet": "dotnet run -c Release ../../../../../fable-test/fable-test.fsproj out-test --classTypes --typescript && npm run build-test-transform",
"build-test-node-ts": "node out-node/app.js ../../../../../fable-test/fable-test.fsproj out-test --classTypes --typescript && npm run build-test-transform -- --typescript",
"build-test-dotnet-ts": "dotnet run -c Release ../../../../../fable-test/fable-test.fsproj out-test --classTypes --typescript && npm run build-test-transform -- --typescript",
"build-test-dotnet-opt": "dotnet run -c Release ../../../../../fable-test/fable-test.fsproj out-test --optimize-fcs && npm run build-test-transform",
"build-test-transform": "node transform ../../../../../fable-test/fable-test.fsproj out-test ../../../../build/fable-library --typescript",
"build-test-transform": "node transform ../../../../../fable-test/fable-test.fsproj out-test ../../../../build/fable-library",
"test-node": "node ./out-test/src/test.js",

"prebuild-tests-dotnet": "if exist out-tests (rmdir /s /q out-tests)",
"build-tests-node": "node out-node/app.js ../../../../tests/Main/Fable.Tests.fsproj out-tests && npm run build-tests-transform",
"build-tests-dotnet": "dotnet run -c Release ../../../../tests/Main/Fable.Tests.fsproj out-tests && npm run build-tests-transform",
"build-tests-dotnet-ts": "dotnet run -c Release ../../../../tests/Main/Fable.Tests.fsproj out-tests --classTypes --typescript && npm run build-tests-transform -- --typescript",
"build-tests-dotnet-opt": "dotnet run -c Release ../../../../tests/Main/Fable.Tests.fsproj out-tests --optimize-fcs && npm run build-tests-transform",
"build-tests-transform": "node transform ../../../../tests/Main/Fable.Tests.fsproj out-tests ../../../../build/fable-library",
"pretests": "npm run build-tests-dotnet",
Expand Down
Loading

0 comments on commit 2d0d3ba

Please sign in to comment.