@@ -375,6 +375,31 @@ type CapturingDiagnosticsLogger(nm, ?eagerFormat) =
375375 let errors = diagnostics.ToArray()
376376 errors |> Array.iter diagnosticsLogger.DiagnosticSink
377377
378+ type ConcurrentCapturingDiagnosticsLogger ( nm , ? eagerFormat ) =
379+ inherit DiagnosticsLogger( nm)
380+ let mutable errorCount = 0
381+ let diagnostics = System.Collections.Concurrent.ConcurrentQueue()
382+
383+ override _.DiagnosticSink ( diagnostic , severity ) =
384+ let diagnostic =
385+ match eagerFormat with
386+ | None -> diagnostic
387+ | Some f -> f diagnostic
388+
389+ if severity = FSharpDiagnosticSeverity.Error then
390+ Interlocked.Increment & errorCount |> ignore
391+
392+ diagnostics.Enqueue( diagnostic, severity)
393+
394+ override _.ErrorCount = errorCount
395+
396+ member _.Diagnostics = diagnostics |> Seq.toList
397+
398+ member _.CommitDelayedDiagnostics ( diagnosticsLogger : DiagnosticsLogger ) =
399+ // Eagerly grab all the errors and warnings from the mutable collection
400+ let errors = diagnostics.ToArray()
401+ errors |> Array.iter diagnosticsLogger.DiagnosticSink
402+
378403/// Type holds thread-static globals for use by the compiler.
379404type DiagnosticsThreadStatics =
380405 static let buildPhase = new AsyncLocal< BuildPhase>()
@@ -517,6 +542,17 @@ let UseTransformedDiagnosticsLogger (transformer: DiagnosticsLogger -> #Diagnost
517542let UseDiagnosticsLogger newLogger =
518543 UseTransformedDiagnosticsLogger( fun _ -> newLogger)
519544
545+ let CaptureDiagnosticsConcurrently () =
546+ let newLogger = ConcurrentCapturingDiagnosticsLogger( " CaptureDiagnosticsConcurrently" )
547+ let oldLogger = DiagnosticsThreadStatics.DiagnosticsLogger
548+ DiagnosticsThreadStatics.DiagnosticsLogger <- newLogger
549+
550+ { new IDisposable with
551+ member _.Dispose () =
552+ newLogger.CommitDelayedDiagnostics oldLogger
553+ DiagnosticsThreadStatics.DiagnosticsLogger <- oldLogger
554+ }
555+
520556let SetThreadBuildPhaseNoUnwind ( phase : BuildPhase ) =
521557 DiagnosticsThreadStatics.BuildPhase <- phase
522558
@@ -855,14 +891,11 @@ type StackGuard(maxDepth: int, name: string) =
855891
856892 try
857893 if depth % maxDepth = 0 then
858- let diagnosticsLogger = DiagnosticsThreadStatics.DiagnosticsLogger
859- let buildPhase = DiagnosticsThreadStatics.BuildPhase
860894 let ct = Cancellable.Token
861895
862896 async {
863897 do ! Async.SwitchToNewThread()
864898 Thread.CurrentThread.Name <- $" F# Extra Compilation Thread for {name} (depth {depth})"
865- use _scope = new CompilationGlobalsScope( diagnosticsLogger, buildPhase)
866899 use _token = Cancellable.UsingToken ct
867900 return f ()
868901 }
0 commit comments