Skip to content
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
* Allow `| null` nullable annotation on a `[<MeasureAnnotatedAbbreviation>]` over a reference type (e.g. the FSharp.UMX `type string<[<Measure>] 'm> = string` pattern). ([Issue #19657](https://github.com/dotnet/fsharp/issues/19657))
* Fix `[<Struct>] ?param` optional parameters could not be passed using the explicit `?param = expr` caller-side syntax with a `ValueOption` value. ([Issue #19711](https://github.com/dotnet/fsharp/issues/19711), [PR #19742](https://github.com/dotnet/fsharp/pull/19742))
* Fix signature conformance: overloaded member with unit parameter `M(())` now matches sig `member M: unit -> unit`. ([Issue #19596](https://github.com/dotnet/fsharp/issues/19596), [PR #19615](https://github.com/dotnet/fsharp/pull/19615))
* Fix `--quiet` not suppressing NuGet restore output on stdout in F# Interactive ([Issue #18086](https://github.com/dotnet/fsharp/issues/18086))
* Reference assembly MVIDs are now deterministic across compiler invocations. Previously, `--refout` / `<ProduceReferenceAssembly>true</ProduceReferenceAssembly>` produced a different MVID every build because the implied signature hash used .NET's randomized `String.GetHashCode()`. ([Issue #19751](https://github.com/dotnet/fsharp/issues/19751), [PR #19801](https://github.com/dotnet/fsharp/pull/19801))
* Parser: recover on unfinished if and binary expressions
([PR #19724](https://github.com/dotnet/fsharp/pull/19724))
Expand Down
6 changes: 5 additions & 1 deletion src/Compiler/Interactive/fsi.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2819,8 +2819,12 @@ type internal FsiDynamicCompiler

if result.Success then

// Under --quiet, route NuGet restore stdout to stderr.
let stdOutSink: System.IO.TextWriter =
if tcConfigB.noFeedback then Console.Error else Console.Out

for line in result.StdOut do
Console.Out.WriteLine(line)
stdOutSink.WriteLine(line)

for line in result.StdError do
Console.Error.WriteLine(line)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,50 @@ module FsiCliTests =
let result = runFsiProcess [option]
Assert.NotEqual(0, result.ExitCode)
Assert.Contains(expectedError, result.StdErr)

// ============================================================================
// Issue #18086: --quiet must suppress NuGet restore stdout chatter
// ============================================================================

let private writeTempScript (content: string) : string =
let path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), $"fsi_quiet_{System.Guid.NewGuid():N}.fsx")
System.IO.File.WriteAllText(path, content)
path

let private runFsiScript (extraArgs: string list) (scriptBody: string) =
let scriptPath = writeTempScript scriptBody
try
let result = runFsiProcess (extraArgs @ [scriptPath])
result
finally
try System.IO.File.Delete(scriptPath) with _ -> ()

[<Fact>]
let ``FSI quiet mode suppresses NuGet restore output from stdout`` () =
let script = """
#r "nuget: Newtonsoft.Json, 13.0.3"
printfn "RESULT_MARKER_18086"
"""
let result = runFsiScript ["--quiet"] script
Assert.Equal(0, result.ExitCode)
Assert.Contains("RESULT_MARKER_18086", result.StdOut)
Assert.DoesNotContain("Determining projects to restore", result.StdOut)
Assert.DoesNotContain("Restored ", result.StdOut)
Assert.DoesNotContain("NU1", result.StdOut)

[<Fact>]
let ``FSI default (non-quiet) mode still evaluates script and prints user output`` () =
let script = """
#r "nuget: Newtonsoft.Json, 13.0.3"
printfn "RESULT_MARKER_18086_DEFAULT"
"""
let result = runFsiScript [] script
Assert.Equal(0, result.ExitCode)
Assert.Contains("RESULT_MARKER_18086_DEFAULT", result.StdOut)

[<Fact>]
let ``FSI quiet mode still prints user printfn output to stdout`` () =
let script = """printfn "hello from quiet script" """
let result = runFsiScript ["--quiet"] script
Assert.Equal(0, result.ExitCode)
Assert.Contains("hello from quiet script", result.StdOut)
Loading