diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index 2d67a9d450b..f6af3112c68 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -68,6 +68,7 @@ * Allow `| null` nullable annotation on a `[]` over a reference type (e.g. the FSharp.UMX `type string<[] 'm> = string` pattern). ([Issue #19657](https://github.com/dotnet/fsharp/issues/19657)) * Fix `[] ?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` / `true` 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)) diff --git a/src/Compiler/Interactive/fsi.fs b/src/Compiler/Interactive/fsi.fs index 1ff957e77a8..30801263752 100644 --- a/src/Compiler/Interactive/fsi.fs +++ b/src/Compiler/Interactive/fsi.fs @@ -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) diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsi/FsiCliTests.fs b/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsi/FsiCliTests.fs index a66269e63f6..dbb08a42edb 100644 --- a/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsi/FsiCliTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsi/FsiCliTests.fs @@ -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 _ -> () + + [] + 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) + + [] + 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) + + [] + 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)