Skip to content

Commit d6db771

Browse files
T-GroCopilot
andauthored
Fix #18086: suppress NuGet restore stdout under FSI --quiet (#19808)
* Fix #18086: suppress NuGet restore stdout under FSI --quiet When --quiet (tcConfigB.noFeedback) is active, route the captured stdout of the NuGet restore subprocess to stderr instead of stdout so that warnings like NU1608 and MSBuild `Determining projects to restore...` chatter no longer pollute FSI stdout. Default (non-quiet) behavior is unchanged. result.StdError continues to go to stderr unconditionally. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add release notes entry for #18086 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Apply remaining changes * Remove executor artifact --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 022cd1a commit d6db771

3 files changed

Lines changed: 53 additions & 1 deletion

File tree

docs/release-notes/.FSharp.Compiler.Service/11.0.100.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
* 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))
6969
* 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))
7070
* 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))
71+
* Fix `--quiet` not suppressing NuGet restore output on stdout in F# Interactive ([Issue #18086](https://github.com/dotnet/fsharp/issues/18086))
7172
* 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))
7273
* Parser: recover on unfinished if and binary expressions
7374
([PR #19724](https://github.com/dotnet/fsharp/pull/19724))

src/Compiler/Interactive/fsi.fs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2819,8 +2819,12 @@ type internal FsiDynamicCompiler
28192819

28202820
if result.Success then
28212821

2822+
// Under --quiet, route NuGet restore stdout to stderr.
2823+
let stdOutSink: System.IO.TextWriter =
2824+
if tcConfigB.noFeedback then Console.Error else Console.Out
2825+
28222826
for line in result.StdOut do
2823-
Console.Out.WriteLine(line)
2827+
stdOutSink.WriteLine(line)
28242828

28252829
for line in result.StdError do
28262830
Console.Error.WriteLine(line)

tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsi/FsiCliTests.fs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,50 @@ module FsiCliTests =
6767
let result = runFsiProcess [option]
6868
Assert.NotEqual(0, result.ExitCode)
6969
Assert.Contains(expectedError, result.StdErr)
70+
71+
// ============================================================================
72+
// Issue #18086: --quiet must suppress NuGet restore stdout chatter
73+
// ============================================================================
74+
75+
let private writeTempScript (content: string) : string =
76+
let path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), $"fsi_quiet_{System.Guid.NewGuid():N}.fsx")
77+
System.IO.File.WriteAllText(path, content)
78+
path
79+
80+
let private runFsiScript (extraArgs: string list) (scriptBody: string) =
81+
let scriptPath = writeTempScript scriptBody
82+
try
83+
let result = runFsiProcess (extraArgs @ [scriptPath])
84+
result
85+
finally
86+
try System.IO.File.Delete(scriptPath) with _ -> ()
87+
88+
[<Fact>]
89+
let ``FSI quiet mode suppresses NuGet restore output from stdout`` () =
90+
let script = """
91+
#r "nuget: Newtonsoft.Json, 13.0.3"
92+
printfn "RESULT_MARKER_18086"
93+
"""
94+
let result = runFsiScript ["--quiet"] script
95+
Assert.Equal(0, result.ExitCode)
96+
Assert.Contains("RESULT_MARKER_18086", result.StdOut)
97+
Assert.DoesNotContain("Determining projects to restore", result.StdOut)
98+
Assert.DoesNotContain("Restored ", result.StdOut)
99+
Assert.DoesNotContain("NU1", result.StdOut)
100+
101+
[<Fact>]
102+
let ``FSI default (non-quiet) mode still evaluates script and prints user output`` () =
103+
let script = """
104+
#r "nuget: Newtonsoft.Json, 13.0.3"
105+
printfn "RESULT_MARKER_18086_DEFAULT"
106+
"""
107+
let result = runFsiScript [] script
108+
Assert.Equal(0, result.ExitCode)
109+
Assert.Contains("RESULT_MARKER_18086_DEFAULT", result.StdOut)
110+
111+
[<Fact>]
112+
let ``FSI quiet mode still prints user printfn output to stdout`` () =
113+
let script = """printfn "hello from quiet script" """
114+
let result = runFsiScript ["--quiet"] script
115+
Assert.Equal(0, result.ExitCode)
116+
Assert.Contains("hello from quiet script", result.StdOut)

0 commit comments

Comments
 (0)