Skip to content

Commit c8b4cef

Browse files
alfonsogarciacaroncave
authored andcommitted
Add Compile to service_slim and pub-sub pattern
1 parent c2af937 commit c8b4cef

File tree

3 files changed

+82
-12
lines changed

3 files changed

+82
-12
lines changed

fcs/service_slim.fs

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ module internal ParseAndCheck =
110110
let tcConfig =
111111
let tcConfigB =
112112
TcConfigBuilder.CreateNew(SimulatedMSBuildReferenceResolver.getResolver(),
113+
includewin32manifest=false,
114+
framework=false,
115+
portablePDB=false,
113116
defaultFSharpBinariesDir=FSharpCheckerResultsSettings.defaultFSharpBinariesDir,
114117
reduceMemoryUsage=ReduceMemoryFlag.Yes,
115118
implicitIncludeDir=Path.GetDirectoryName(projectOptions.ProjectFileName),
@@ -231,12 +234,23 @@ module internal ParseAndCheck =
231234
loadClosure, implFile, sink.GetOpenDeclarations())
232235
FSharpCheckFileResults (fileName, errors, Some scope, parseResults.DependencyFiles, None, keepAssemblyContents)
233236

234-
let TypeCheckClosedInputSet (parseResults: FSharpParseFileResults[], tcState, compilerState) =
237+
let TypeCheckClosedInputSet (parseResults: FSharpParseFileResults[], tcState, compilerState, subscriber) =
235238
let cachedTypeCheck (tcState, moduleNamesDict) (parseRes: FSharpParseFileResults) =
236239
let checkCacheKey = parseRes.FileName
240+
237241
let typeCheckOneInput _fileName =
238242
TypeCheckOneInputEntry (parseRes, TcResultsSink.NoSink, tcState, moduleNamesDict, compilerState)
239-
compilerState.checkCache.GetOrAdd(checkCacheKey, typeCheckOneInput)
243+
244+
let (result, errors), (tcState, moduleNamesDict) = compilerState.checkCache.GetOrAdd(checkCacheKey, typeCheckOneInput)
245+
246+
let _, _, implFile, _ = result
247+
match subscriber, implFile with
248+
| Some subscriber, Some implFile ->
249+
let cenv = SymbolEnv(compilerState.tcGlobals, tcState.Ccu, Some tcState.CcuSig, compilerState.tcImports)
250+
FSharpImplementationFileContents(cenv, implFile) |> subscriber
251+
| _ -> ()
252+
253+
(result, errors), (tcState, moduleNamesDict)
240254

241255
let results, (tcState, moduleNamesDict) =
242256
((tcState, Map.empty), parseResults) ||> Array.mapFold cachedTypeCheck
@@ -256,7 +270,6 @@ module internal ParseAndCheck =
256270
errors |> Array.iter (Array.sortInPlaceBy (fun x -> x.StartLine, x.StartColumn))
257271
errors |> Array.concat
258272

259-
260273
type InteractiveChecker internal (compilerStateCache) =
261274

262275
static member Create(projectOptions: FSharpProjectOptions) =
@@ -269,32 +282,66 @@ type InteractiveChecker internal (compilerStateCache) =
269282
compilerState.checkCache.Clear()
270283
}
271284

285+
member _.GetImportedAssemblies() = async {
286+
let! compilerState = compilerStateCache.Get()
287+
let tcImports = compilerState.tcImports
288+
let tcGlobals = compilerState.tcGlobals
289+
return
290+
tcImports.GetImportedAssemblies()
291+
|> List.map (fun x -> FSharpAssembly(tcGlobals, tcImports, x.FSharpViewOfMetadata))
292+
}
293+
294+
/// Compile project to file. If project has already been type checked,
295+
/// check results will be taken from the cache.
296+
member _.Compile(fileNames: string[], sourceReader: string -> int * Lazy<string>, outFile: string) = async {
297+
let! compilerState = compilerStateCache.Get()
298+
let parsingOptions = FSharpParsingOptions.FromTcConfig(compilerState.tcConfig, fileNames, false)
299+
let parseResults = fileNames |> Array.map (fun fileName ->
300+
let sourceHash, source = sourceReader fileName
301+
ParseFile(fileName, sourceHash, source, parsingOptions, compilerState))
302+
303+
let (tcState, topAttrs, tcImplFiles, _tcEnvAtEnd, _moduleNamesDict, _tcErrors) =
304+
TypeCheckClosedInputSet (parseResults, compilerState.tcInitialState, compilerState, None)
305+
306+
let ctok = CompilationThreadToken()
307+
let errors, errorLogger, _loggerProvider = CompileHelpers.mkCompilationErrorHandlers()
308+
let exitCode =
309+
CompileHelpers.tryCompile errorLogger (fun exiter ->
310+
compileOfTypedAst (ctok, compilerState.tcGlobals, compilerState.tcImports, tcState.Ccu,
311+
tcImplFiles, topAttrs, compilerState.tcConfig, outFile, errorLogger, exiter))
312+
313+
return errors.ToArray(), exitCode
314+
}
315+
272316
/// Parses and checks the whole project, good for compilers (Fable etc.)
273317
/// Does not retain name resolutions and symbol uses which are quite memory hungry (so no intellisense etc.).
274318
/// Already parsed files will be cached so subsequent compilations will be faster.
275-
member _.ParseAndCheckProject (projectFileName: string, fileNames: string[], sourceReader: string -> int * Lazy<string>, ?lastFile: string) = async {
319+
member _.ParseAndCheckProject (projectFileName: string, fileNames: string[], sourceReader: string -> int * Lazy<string>,
320+
?lastFile: string, ?subscriber: FSharpImplementationFileContents -> unit) = async {
276321
let! compilerState = compilerStateCache.Get()
277322
// parse files
278323
let parsingOptions = FSharpParsingOptions.FromTcConfig(compilerState.tcConfig, fileNames, false)
279-
// We can paralellize this, but only in the first compilation because later it causes issues when invalidating the cache
280-
let parseResults = // measureTime <| fun _ ->
324+
let parseResults =
281325
let fileNames =
282326
match lastFile with
283327
| None -> fileNames
284328
| Some fileName ->
285329
let fileIndex = fileNames |> Array.findIndex ((=) fileName)
286330
fileNames |> Array.take (fileIndex + 1)
287331

288-
fileNames |> Array.map (fun fileName ->
332+
let parseFile fileName =
289333
let sourceHash, source = sourceReader fileName
290334
ParseFile(fileName, sourceHash, source, parsingOptions, compilerState)
291-
)
292-
// printfn "FCS: Parsing finished in %ims" ms
335+
336+
// Don't parallelize if we have cached files, as it would create issues with invalidation
337+
if compilerState.parseCache.Count = 0 then
338+
fileNames |> Array.Parallel.map parseFile
339+
else
340+
fileNames |> Array.map parseFile
293341

294342
// type check files
295343
let (tcState, topAttrs, tcImplFiles, _tcEnvAtEnd, _moduleNamesDict, tcErrors) = // measureTime <| fun _ ->
296-
TypeCheckClosedInputSet (parseResults, compilerState.tcInitialState, compilerState)
297-
// printfn "FCS: Checking finished in %ims" ms
344+
TypeCheckClosedInputSet (parseResults, compilerState.tcInitialState, compilerState, subscriber)
298345

299346
// make project results
300347
let parseErrors = parseResults |> Array.collect (fun p -> p.Diagnostics)
@@ -325,7 +372,7 @@ type InteractiveChecker internal (compilerStateCache) =
325372

326373
// type check files before file
327374
let tcState, topAttrs, tcImplFiles, _tcEnvAtEnd, moduleNamesDict, tcErrors =
328-
TypeCheckClosedInputSet (parseResults, compilerState.tcInitialState, compilerState)
375+
TypeCheckClosedInputSet (parseResults, compilerState.tcInitialState, compilerState, None)
329376

330377
// parse and type check file
331378
let parseFileResults = parseFile fileName

src/Compiler/Driver/fsc.fs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,3 +1270,20 @@ let CompileFromCommandLineArguments
12701270
|> main4 (tcImportsCapture, dynamicAssemblyCreator)
12711271
|> main5
12721272
|> main6 dynamicAssemblyCreator
1273+
1274+
let compileOfTypedAst
1275+
(ctok, tcGlobals, tcImports: TcImports, generatedCcu: CcuThunk, typedImplFiles,
1276+
topAttrs, tcConfig: TcConfig, outfile, errorLogger, exiter: Exiter) =
1277+
1278+
let tcImportsCapture = None
1279+
let dynamicAssemblyCreator = None
1280+
let assemblyName = Path.GetFileNameWithoutExtension(outfile)
1281+
// Doubling here tcImports as frameworkTcImports, seems to work...
1282+
let frameworkTcImports = tcImports
1283+
1284+
Args (ctok, tcGlobals, tcImports, frameworkTcImports, generatedCcu, typedImplFiles, topAttrs, tcConfig, outfile, None, assemblyName, errorLogger, exiter)
1285+
|> main2
1286+
|> main3
1287+
|> main4 (tcImportsCapture, dynamicAssemblyCreator)
1288+
|> main5
1289+
|> main6 dynamicAssemblyCreator

src/Compiler/Service/service.fsi

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ open FSharp.Compiler.Symbols
1515
open FSharp.Compiler.Syntax
1616
open FSharp.Compiler.Text
1717
open FSharp.Compiler.Tokenization
18+
open FSharp.Compiler.ErrorLogger
19+
open FSharp.Compiler.Driver
20+
21+
module internal CompileHelpers =
22+
val mkCompilationErrorHandlers: unit -> ResizeArray<FSharpDiagnostic> * ErrorLogger * ErrorLoggerProvider
23+
val tryCompile: ErrorLogger -> (Exiter -> unit) -> int
1824

1925
[<Experimental "This type is experimental and likely to be removed in the future.">]
2026
[<RequireQualifiedAccess>]

0 commit comments

Comments
 (0)