Skip to content

Commit

Permalink
Pass otherFSharpOptions to fable-standalone
Browse files Browse the repository at this point in the history
  • Loading branch information
alfonsogarciacaro committed Sep 26, 2019
1 parent 32f1090 commit 565bf9f
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 30 deletions.
7 changes: 4 additions & 3 deletions src/fable-standalone/src/Interfaces.fs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type IChecker =
interface end

type IParseResults =
abstract OtherFSharpOptions: string[]
abstract Errors: Error[]

type IBabelResult =
Expand All @@ -50,9 +51,9 @@ type IFableManager =
abstract CreateChecker: references: string[] * readAllBytes: (string -> byte[]) * defines: string[] * optimize: bool -> IChecker
abstract CreateChecker: references: string[] * readAllBytes: (string -> byte[]) * otherOptions: string[] -> IChecker
abstract ClearParseCaches: checker: IChecker -> unit
abstract ParseFSharpScript: checker: IChecker * fileName: string * source: string -> IParseResults
abstract ParseFSharpProject: checker: IChecker * projectFileName: string * fileNames: string[] * sources: string[] -> IParseResults
abstract ParseFSharpFileInProject: checker: IChecker * fileName: string * projectFileName: string * fileNames: string[] * sources: string[] -> IParseResults
abstract ParseFSharpScript: checker: IChecker * fileName: string * source: string * ?otherFSharpOptions: string[] -> IParseResults
abstract ParseFSharpProject: checker: IChecker * projectFileName: string * fileNames: string[] * sources: string[] * ?otherFSharpOptions: string[] -> IParseResults
abstract ParseFSharpFileInProject: checker: IChecker * fileName: string * projectFileName: string * fileNames: string[] * sources: string[] * ?otherFSharpOptions: string[] -> IParseResults
abstract GetParseErrors: parseResults: IParseResults -> Error[]
abstract GetDeclarationLocation: parseResults: IParseResults * line: int * col: int * lineText: string -> Async<Range option>
abstract GetToolTipText: parseResults: IParseResults * line: int * col: int * lineText: string -> Async<string[]>
Expand Down
47 changes: 26 additions & 21 deletions src/fable-standalone/src/Main.fs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ type ParseResults (optimizedProject: Lazy<Project>,
unoptimizedProject: Lazy<Project>,
parseFileResultsOpt: FSharpParseFileResults option,
checkFileResultsOpt: FSharpCheckFileResults option,
checkProjectResults: FSharpCheckProjectResults) =
checkProjectResults: FSharpCheckProjectResults,
otherFSharpOptions: string[]) =

member __.GetProject (optimized: bool) =
if optimized
Expand All @@ -41,6 +42,7 @@ type ParseResults (optimizedProject: Lazy<Project>,
member __.CheckProjectResults = checkProjectResults

interface IParseResults with
member __.OtherFSharpOptions = otherFSharpOptions
member __.Errors = checkProjectResults.Errors |> Array.map mapError

let inline private tryGetLexerSymbolIslands (sym: Lexer.LexerSymbol) =
Expand Down Expand Up @@ -104,12 +106,12 @@ let convertGlyph glyph =
| FSharpGlyph.Event ->
Glyph.Event

let makeProjOptions projectFileName fileNames =
let makeProjOptions projectFileName fileNames otherFSharpOptions =
let projOptions: FSharpProjectOptions =
{ ProjectFileName = projectFileName
ProjectId = None
SourceFiles = fileNames
OtherOptions = [| |]
OtherOptions = otherFSharpOptions
ReferencedProjects = [| |]
IsIncompleteTypeCheckEnvironment = false
UseScriptResolutionRules = false
Expand All @@ -131,27 +133,27 @@ let makeProject projectOptions (projectResults: FSharpCheckProjectResults) optim
implFiles |> Seq.map (fun file -> Fable.Path.normalizePathAndEnsureFsExtension file.FileName, file) |> dict
Project(projectOptions, implFilesMap, projectResults.Errors)

let parseFSharpScript (checker: InteractiveChecker) projectFileName fileName source =
let parseFSharpScript (checker: InteractiveChecker) projectFileName fileName source otherFSharpOptions =
let parseResults, checkResults, projectResults =
checker.ParseAndCheckScript (projectFileName, fileName, source)
let projectOptions = makeProjOptions projectFileName [| fileName |]
let projectOptions = makeProjOptions projectFileName [| fileName |] otherFSharpOptions
let optimizedProject = lazy (makeProject projectOptions projectResults true)
let unoptimizedProject = lazy (makeProject projectOptions projectResults false)
ParseResults (optimizedProject, unoptimizedProject, Some parseResults, Some checkResults, projectResults)
ParseResults (optimizedProject, unoptimizedProject, Some parseResults, Some checkResults, projectResults, otherFSharpOptions)

let parseFSharpProject (checker: InteractiveChecker) projectFileName fileNames sources =
let parseFSharpProject (checker: InteractiveChecker) projectFileName fileNames sources otherFSharpOptions =
let projectResults = checker.ParseAndCheckProject (projectFileName, fileNames, sources)
let projectOptions = makeProjOptions projectFileName fileNames
let projectOptions = makeProjOptions projectFileName fileNames otherFSharpOptions
let optimizedProject = lazy (makeProject projectOptions projectResults true)
let unoptimizedProject = lazy (makeProject projectOptions projectResults false)
ParseResults (optimizedProject, unoptimizedProject, None, None, projectResults)
ParseResults (optimizedProject, unoptimizedProject, None, None, projectResults, otherFSharpOptions)

let parseFSharpFileInProject (checker: InteractiveChecker) fileName projectFileName fileNames sources =
let parseFSharpFileInProject (checker: InteractiveChecker) fileName projectFileName fileNames sources otherFSharpOptions =
let parseResults, checkResultsOpt, projectResults = checker.ParseAndCheckFileInProject (fileName, projectFileName, fileNames, sources)
let projectOptions = makeProjOptions projectFileName fileNames
let projectOptions = makeProjOptions projectFileName fileNames otherFSharpOptions
let optimizedProject = lazy (makeProject projectOptions projectResults true)
let unoptimizedProject = lazy (makeProject projectOptions projectResults false)
ParseResults (optimizedProject, unoptimizedProject, Some parseResults, checkResultsOpt, projectResults)
ParseResults (optimizedProject, unoptimizedProject, Some parseResults, checkResultsOpt, projectResults, otherFSharpOptions)

let tooltipToString (el: FSharpToolTipElement<string>): string[] =
let dataToString (data: FSharpToolTipElementData<string>) =
Expand Down Expand Up @@ -218,11 +220,11 @@ let getCompletionsAtLocation (parseResults: ParseResults) (line: int) (col: int)
return [||]
}

let makeCompiler fableLibrary fileName (project: Project) precompiledLib =
let makeCompiler fableLibrary fileName (project: Project) precompiledLib (otherFSharpOptions: string[]) =
let options: Fable.CompilerOptions =
{ typedArrays = true
clampByteArrays = false
debugMode = true
debugMode = otherFSharpOptions |> Array.exists ((=) "--define:DEBUG")
verbosity = Fable.Verbosity.Normal
outputPublicInlinedFunctions = false
precompiledLib = precompiledLib }
Expand All @@ -248,18 +250,21 @@ let init () =
let c = checker :?> CheckerImpl
c.Checker.ClearCache()

member __.ParseFSharpScript(checker, fileName, source) =
member __.ParseFSharpScript(checker, fileName, source, ?otherFSharpOptions) =
let c = checker :?> CheckerImpl
let otherFSharpOptions = defaultArg otherFSharpOptions [||]
let projectFileName = "project" // TODO: make it an argument
parseFSharpScript c.Checker projectFileName fileName source :> IParseResults
parseFSharpScript c.Checker projectFileName fileName source otherFSharpOptions :> IParseResults

member __.ParseFSharpProject(checker, projectFileName, fileNames, sources) =
member __.ParseFSharpProject(checker, projectFileName, fileNames, sources, ?otherFSharpOptions) =
let c = checker :?> CheckerImpl
parseFSharpProject c.Checker projectFileName fileNames sources :> IParseResults
let otherFSharpOptions = defaultArg otherFSharpOptions [||]
parseFSharpProject c.Checker projectFileName fileNames sources otherFSharpOptions :> IParseResults

member __.ParseFSharpFileInProject(checker, fileName, projectFileName, fileNames, sources) =
member __.ParseFSharpFileInProject(checker, fileName, projectFileName, fileNames, sources, ?otherFSharpOptions) =
let c = checker :?> CheckerImpl
parseFSharpFileInProject c.Checker fileName projectFileName fileNames sources :> IParseResults
let otherFSharpOptions = defaultArg otherFSharpOptions [||]
parseFSharpFileInProject c.Checker fileName projectFileName fileNames sources otherFSharpOptions :> IParseResults

member __.GetParseErrors(parseResults:IParseResults) =
parseResults.Errors
Expand All @@ -279,7 +284,7 @@ let init () =
member __.CompileToBabelAst(fableLibrary:string, parseResults:IParseResults, fileName:string, optimized: bool, ?precompiledLib) =
let res = parseResults :?> ParseResults
let project = res.GetProject (optimized)
let com = makeCompiler fableLibrary fileName project precompiledLib
let com = makeCompiler fableLibrary fileName project precompiledLib parseResults.OtherFSharpOptions
let ast = compileAst com project
let errors =
com.GetLogs()
Expand Down
4 changes: 2 additions & 2 deletions src/fable-standalone/src/Worker/Shared.fs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ open Thoth.Json
type WorkerRequest =
/// * refsExtraSuffix: e.g. add .txt extension to enable gzipping in Github Pages
| CreateChecker of refsDirUrl: string * extraRefs: string[] * refsExtraSuffix: string option * libJsonUrl: string option
| ParseCode of fsharpCode: string
| CompileCode of fsharpCode: string * optimize: bool
| ParseCode of fsharpCode: string * otherFSharpOptions: string[]
| CompileCode of fsharpCode: string * otherFSharpOptions: string[] * optimize: bool
| GetTooltip of id: Guid * line: int * column: int * lineText: string
| GetCompletions of id: Guid * line: int * column: int * lineText: string
| GetDeclarationLocation of id: Guid * line: int * column: int * lineText: string
Expand Down
8 changes: 4 additions & 4 deletions src/fable-standalone/src/Worker/Worker.fs
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,14 @@ let rec loop (box: MailboxProcessor<WorkerRequest>) (state: State) = async {
| None, _
| Some _, CreateChecker _ -> return! loop box state

| Some fable, ParseCode fsharpCode ->
let res = fable.Manager.ParseFSharpScript(fable.Checker, FILE_NAME, fsharpCode)
| Some fable, ParseCode(fsharpCode, otherFSharpOptions) ->
let res = fable.Manager.ParseFSharpScript(fable.Checker, FILE_NAME, fsharpCode, otherFSharpOptions)
ParsedCode res.Errors |> state.Worker.Post
return! loop box { state with CurrentResults = Some res }

| Some fable, CompileCode(fsharpCode, optimize) ->
| Some fable, CompileCode(fsharpCode, otherFSharpOptions, optimize) ->
try
let (parseResults, parsingTime) = measureTime fable.Manager.ParseFSharpScript (fable.Checker, FILE_NAME, fsharpCode)
let (parseResults, parsingTime) = measureTime (fun () -> fable.Manager.ParseFSharpScript(fable.Checker, FILE_NAME, fsharpCode, otherFSharpOptions)) ()
let (res, fableTransformTime) = measureTime (fun () ->
fable.Manager.CompileToBabelAst("fable-library", parseResults, FILE_NAME, optimize, fun x -> resolveLibCall(fable.LibMap, x))) ()
let (jsCode, babelTime, babelErrors) =
Expand Down

6 comments on commit 565bf9f

@ncave
Copy link
Collaborator

@ncave ncave commented on 565bf9f Sep 26, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alfonsogarciacaro This is actually not necessary, you can already pass otherOptions when you create the checker (see IFableManager.CreateChecker).

It doesn't hurt either, but the options you added above are staying on the client side, they'll not be sent to FCS-Fable. The only way to set otherOptions right now is to create a new checker. We can change that, but the typecheck caching will have to change to account for options being changed on the fly, probably by flushing the cache (which is similar to making a new checker).

@alfonsogarciacaro
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I realized that when testing the REPL :/ Anyways, it's working now :) When activating "Preview F# features" you can open static classes but nameof is not working yet. I guess we need to create new metadata from latest FSharp.Core for that.

@ncave
Copy link
Collaborator

@ncave ncave commented on 565bf9f Sep 26, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alfonsogarciacaro This is awesome, thanks a lot.
The export branch is rebased, if you want to run the Export.Metadata target for sdk 3.0 binaries (I promise to do it next time).

@alfonsogarciacaro
Copy link
Member Author

@alfonsogarciacaro alfonsogarciacaro commented on 565bf9f Sep 26, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I tried running Export.Metadata and also GenerateMetadata in the repl repository (after some rework), but the result is very strange. The new assemblies seem to work except for FSharp.Core, I cannot open the namespace and everything that's coming from there fails with "The value or constructor 'xxx' is not defined."

However FSharp.Core.dll is correctly generated and I can see the browser is loading it 😕

image

@ncave
Copy link
Collaborator

@ncave ncave commented on 565bf9f Sep 28, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alfonsogarciacaro Yes, it is strange, supposedly the only difference in 4.7.0 is that it now references netstandard2.0.
Let's stick with the previous version of FSharp.Core (4.6.2) (only for the REPL, of course) until we figure out what to do with 4.7.0.

@ncave
Copy link
Collaborator

@ncave ncave commented on 565bf9f Sep 28, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alfonsogarciacaro
Turns out FSharp.Core 4.7.0 was missing some dependencies (added in #1916):
System.Net.Requests and System.Net.WebClient.

Please sign in to comment.