Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 157 additions & 37 deletions src/Fable.Cli/Main.fs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/Fable.Transforms/Babel/Fable2Babel.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5059,6 +5059,7 @@ module Compiler =
member _.GetInlineExpr(fullName) = com.GetInlineExpr(fullName)

member _.AddWatchDependency(fileName) = com.AddWatchDependency(fileName)
member _.AddSignatureDependency(fileName) = com.AddSignatureDependency(fileName)

member _.AddLog(msg, severity, ?range, ?fileName: string, ?tag: string) =
com.AddLog(msg, severity, ?range = range, ?fileName = fileName, ?tag = tag)
Expand Down
1 change: 1 addition & 0 deletions src/Fable.Transforms/Beam/Fable2Beam.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3842,6 +3842,7 @@ let transformFile (com: Fable.Compiler) (file: File) : Beam.ErlModule =
member _.TryGetEntity(ref) = com.TryGetEntity(ref)
member _.GetInlineExpr(key) = com.GetInlineExpr(key)
member _.AddWatchDependency(file) = com.AddWatchDependency(file)
member _.AddSignatureDependency(file) = com.AddSignatureDependency(file)

member _.AddLog(msg, severity, ?range, ?fileName, ?tag) =
com.AddLog(msg, severity, ?range = range, ?fileName = fileName, ?tag = tag)
Expand Down
1 change: 1 addition & 0 deletions src/Fable.Transforms/Dart/Fable2Dart.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3208,6 +3208,7 @@ module Compiler =
member _.GetInlineExpr(fullName) = com.GetInlineExpr(fullName)

member _.AddWatchDependency(fileName) = com.AddWatchDependency(fileName)
member _.AddSignatureDependency(fileName) = com.AddSignatureDependency(fileName)

member _.AddLog(msg, severity, ?range, ?fileName: string, ?tag: string) =
com.AddLog(msg, severity, ?range = range, ?fileName = fileName, ?tag = tag)
Expand Down
3 changes: 3 additions & 0 deletions src/Fable.Transforms/FSharp2Fable.Util.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2432,6 +2432,7 @@ module Util =
if not com.IsPrecompilingInlineFunction && file = com.CurrentFile then
makeIdentExpr entityName
else
com.AddSignatureDependency(file)
makeInternalClassImport com ent entityName file

let entityIdent (com: Compiler) (ent: Fable.EntityRef) = entityIdentWithSuffix com ent ""
Expand Down Expand Up @@ -2514,6 +2515,8 @@ module Util =
if hasOverloadSuffix then
com.AddWatchDependency(file)

com.AddSignatureDependency(file)

// Private values are not exported so they can't be imported by call sites in other files.
// We need to handle it manually because Fable handle resolve inline function itself
if
Expand Down
16 changes: 13 additions & 3 deletions src/Fable.Transforms/FSharp2Fable.fs
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,14 @@ let private transformExpr (com: IFableCompiler) (ctx: Context) appliedGenArgs fs

| FSharpExprPatterns.Const(value, typ) ->
let typ = makeType ctx.GenericArgs typ

// Enum cases reach Fable as their numeric value, so files using them must follow the enum declaration
do
match typ with
| Fable.Number(_, Fable.NumberInfo.IsEnum entRef) ->
entRef.SourcePath |> Option.iter com.AddSignatureDependency
| _ -> ()

let expr = makeTypeConst (makeRangeFrom fsExpr) typ value
return expr

Expand Down Expand Up @@ -1485,10 +1493,11 @@ let private transformExpr (com: IFableCompiler) (ctx: Context) appliedGenArgs fs
let! argExprs = transformExprList com ctx argExprs

let genArgs = makeTypeGenArgs ctx.GenericArgs (getGenericArguments fsType)
let entRef = FsEnt.Ref fsType.TypeDefinition
// Record fields are passed by position, so a field reordering in the declaring file changes this call
entRef.SourcePath |> Option.iter com.AddSignatureDependency

return
Fable.NewRecord(argExprs, FsEnt.Ref fsType.TypeDefinition, genArgs)
|> makeValue r
return Fable.NewRecord(argExprs, entRef, genArgs) |> makeValue r

| FSharpExprPatterns.NewAnonRecord(fsType, argExprs) ->
let r = makeRangeFrom fsExpr
Expand Down Expand Up @@ -2947,6 +2956,7 @@ type FableCompiler(com: Compiler) =
member _.TryGetEntity(entRef) = com.TryGetEntity(entRef)
member _.GetInlineExpr(fullName) = com.GetInlineExpr(fullName)
member _.AddWatchDependency(fileName) = com.AddWatchDependency(fileName)
member _.AddSignatureDependency(fileName) = com.AddSignatureDependency(fileName)

member _.AddLog(msg, severity, ?range, ?fileName: string, ?tag: string) =
com.AddLog(msg, severity, ?range = range, ?fileName = fileName, ?tag = tag)
Expand Down
1 change: 1 addition & 0 deletions src/Fable.Transforms/Global/Compiler.fs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ type Compiler =
abstract TryGetEntity: Fable.EntityRef -> Fable.Entity option
abstract GetInlineExpr: string -> InlineExpr
abstract AddWatchDependency: file: string -> unit
abstract AddSignatureDependency: file: string -> unit

abstract AddLog:
msg: string * severity: Severity * ?range: SourceLocation * ?fileName: string * ?tag: string -> unit
Expand Down
1 change: 1 addition & 0 deletions src/Fable.Transforms/Php/Fable2Php.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2142,6 +2142,7 @@ type PhpCompiler(com: Fable.Compiler) =
com.AddLog(msg, severity, ?range = rang, ?fileName = fileName, ?tag = tag)

member this.AddWatchDependency(file) = com.AddWatchDependency(file)
member this.AddSignatureDependency(file) = com.AddSignatureDependency(file)

member this.GetImplementationFile(fileName) = com.GetImplementationFile(fileName)

Expand Down
1 change: 1 addition & 0 deletions src/Fable.Transforms/Python/PythonCompiler.fs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ type PythonCompiler(com: Compiler) =
member _.GetInlineExpr(fullName) = com.GetInlineExpr(fullName)

member _.AddWatchDependency(fileName) = com.AddWatchDependency(fileName)
member _.AddSignatureDependency(fileName) = com.AddSignatureDependency(fileName)

member _.AddLog(msg, severity, ?range, ?fileName: string, ?tag: string) =
com.AddLog(msg, severity, ?range = range, ?fileName = fileName, ?tag = tag)
Expand Down
1 change: 1 addition & 0 deletions src/Fable.Transforms/Rust/Fable2Rust.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6439,6 +6439,7 @@ module Compiler =
member _.TryGetEntity(entRef) = com.TryGetEntity(entRef)
member _.GetInlineExpr(fullName) = com.GetInlineExpr(fullName)
member _.AddWatchDependency(fileName) = com.AddWatchDependency(fileName)
member _.AddSignatureDependency(fileName) = com.AddSignatureDependency(fileName)

member _.AddLog(msg, severity, ?range, ?fileName: string, ?tag: string) =
com.AddLog(msg, severity, ?range = range, ?fileName = fileName, ?tag = tag)
Expand Down
151 changes: 151 additions & 0 deletions src/Fable.Transforms/State.fs
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,61 @@ type Assemblies(getPlugin, fsharpAssemblies: FSharpAssembly list, addLog: Severi

member _.Plugins = plugins

type ParameterSignature =
{
Name: string option
IsOptional: bool
IsParamArray: bool
}

type MemberSignature =
{
Type: Fable.Type
Parameters: ParameterSignature list list
IsInline: FSharpInlineAnnotation
IsMutable: bool
Attributes: (string * obj list) list
}

type EntitySignature =
{
Attributes: (string * obj list) list
Kind: bool * bool * bool * bool * bool
Fields: (string * Fable.Type * obj) list
UnionCases: (string * (string * Fable.Type) list) list
}

/// The parts of a file other files can depend on without naming them in their own typed tree
type FileSignature =
{
IsUnknown: bool
Literals: Map<string, obj>
Members: Map<string, MemberSignature>
Entities: Map<string, EntitySignature>
}

static member Unknown =
{
IsUnknown = true
Literals = Map.empty
Members = Map.empty
Entities = Map.empty
}

static member Changed(before: FileSignature, after: FileSignature) =
before.IsUnknown || after.IsUnknown || before <> after

static member LiteralsChanged(before: FileSignature, after: FileSignature) =
before.IsUnknown || after.IsUnknown || before.Literals <> after.Literals

type ImplFile =
{
Declarations: FSharpImplementationFileDeclaration list
RootModule: string
RootComment: FSharpXmlDoc option
Entities: IReadOnlyDictionary<string, Fable.Entity>
InlineExprs: (string * InlineExprLazy) list
Signature: FileSignature
}

static member From(file: FSharpImplementationFileContents) =
Expand All @@ -154,6 +202,96 @@ type ImplFile =

loop entities e.NestedEntities

let signature (declarations: FSharpImplementationFileDeclaration list) =
try
let makeType = FSharp2Fable.TypeHelpers.makeType Map.empty

let attributes (atts: FSharpAttribute seq) =
atts
|> Seq.map (fun att ->
FSharp2Fable.FsEnt.FullName att.AttributeType,
att.ConstructorArguments |> Seq.map snd |> List.ofSeq
)
|> List.ofSeq

let rec members (decls: FSharpImplementationFileDeclaration list) =
decls
|> List.collect (
function
| FSharpImplementationFileDeclaration.Entity(_, decls) -> members decls
| FSharpImplementationFileDeclaration.MemberOrFunctionOrValue(memb, _, _) when
not memb.IsCompilerGenerated && not memb.Accessibility.IsPrivate
->
[ memb ]
| FSharpImplementationFileDeclaration.MemberOrFunctionOrValue _
| FSharpImplementationFileDeclaration.InitAction _ -> []
)

let rec entities (ents: FSharpEntity seq) =
ents |> Seq.collect (fun e -> Seq.append [ e ] (entities e.NestedEntities))

let members = members declarations

{
IsUnknown = false
Literals =
members
|> List.choose (fun memb ->
memb.LiteralValue
|> Option.map (fun value -> FSharp2Fable.Helpers.getMemberUniqueName memb, value)
)
|> Map
Members =
members
|> List.map (fun memb ->
FSharp2Fable.Helpers.getMemberUniqueName memb,
{
Type = makeType memb.FullType
Parameters =
memb.CurriedParameterGroups
|> Seq.map (
Seq.map (fun p ->
{
Name = p.Name
IsOptional = p.IsOptionalArg
IsParamArray = p.IsParamArrayArg
}
)
>> List.ofSeq
)
|> List.ofSeq
IsInline = memb.InlineAnnotation
IsMutable = memb.IsMutable
Attributes = attributes memb.Attributes
}
)
|> Map
Entities =
FSharp2Fable.Compiler.getRootFSharpEntities declarations
|> entities
|> Seq.map (fun e ->
FSharp2Fable.FsEnt.FullName e,
{
Attributes = attributes e.Attributes
Kind = e.IsFSharpRecord, e.IsFSharpUnion, e.IsEnum, e.IsInterface, e.IsValueType
Fields =
e.FSharpFields
|> Seq.map (fun f -> f.Name, makeType f.FieldType, Option.toObj f.LiteralValue)
|> List.ofSeq
UnionCases =
e.UnionCases
|> Seq.map (fun c ->
c.Name,
c.Fields |> Seq.map (fun f -> f.Name, makeType f.FieldType) |> List.ofSeq
)
|> List.ofSeq
}
)
|> Map
}
with _ ->
FileSignature.Unknown

// add all entities to the entity cache
let entities = Dictionary()

Expand All @@ -172,6 +310,7 @@ type ImplFile =
RootModule = rootModule
RootComment = rootComment
InlineExprs = FSharp2Fable.Compiler.getInlineExprs file.FileName declarations
Signature = signature declarations
}

type PrecompiledInfo =
Expand Down Expand Up @@ -319,6 +458,7 @@ type CompilerImpl
?outType: OutputType,
?outDir: string,
?watchDependencies: HashSet<string>,
?signatureDependencies: HashSet<string>,
?logs: ResizeArray<LogEntry>,
?isPrecompilingInlineFunction: bool
)
Expand All @@ -336,6 +476,11 @@ type CompilerImpl
| Some w -> Array.ofSeq w
| None -> [||]

member _.SignatureDependencies =
match signatureDependencies with
| Some w -> Array.ofSeq w
| None -> [||]

interface Compiler with
member _.Options = options
member _.Plugins = project.Assemblies.Plugins
Expand Down Expand Up @@ -369,6 +514,7 @@ type CompilerImpl
outType,
?outDir = outDir,
?watchDependencies = watchDependencies,
?signatureDependencies = signatureDependencies,
logs = logs,
isPrecompilingInlineFunction = true
)
Expand Down Expand Up @@ -429,6 +575,11 @@ type CompilerImpl
| Some watchDependencies when file <> currentFile -> watchDependencies.Add(file) |> ignore
| _ -> ()

member _.AddSignatureDependency(file) =
match signatureDependencies with
| Some signatureDependencies when file <> currentFile -> signatureDependencies.Add(file) |> ignore
| _ -> ()

member _.AddLog(msg, severity, ?range, ?fileName: string, ?tag: string) =
LogEntry.Make(severity, msg, ?range = range, ?fileName = fileName, ?tag = tag)
|> logs.Add
Loading