Skip to content

Commit 8ff644a

Browse files
majochaT-Gro
andauthored
Preserve console encoding when using --utf8output switch without swapping console streams (#17761)
* do not modify stdout * preserve original encoding * Revert "preserve original encoding" This reverts commit 9665470. * add a test * wip * fantomas * add fsi test * utf16 --------- Co-authored-by: Tomas Grosup <[email protected]>
1 parent c802ab5 commit 8ff644a

File tree

6 files changed

+75
-37
lines changed

6 files changed

+75
-37
lines changed

src/Compiler/Driver/fsc.fs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -273,9 +273,6 @@ let SetProcessThreadLocals tcConfigB =
273273
| Some s -> Thread.CurrentThread.CurrentUICulture <- CultureInfo(s)
274274
| None -> ()
275275

276-
if tcConfigB.utf8output then
277-
Console.OutputEncoding <- Encoding.UTF8
278-
279276
let ProcessCommandLineFlags (tcConfigB: TcConfigBuilder, lcidFromCodePage, argv) =
280277
let mutable inputFilesRef = []
281278

@@ -550,6 +547,17 @@ let main1
550547
| Some parallelReferenceResolution -> tcConfigB.parallelReferenceResolution <- parallelReferenceResolution
551548
| None -> ()
552549

550+
if tcConfigB.utf8output && Console.OutputEncoding <> Encoding.UTF8 then
551+
let previousEncoding = Console.OutputEncoding
552+
Console.OutputEncoding <- Encoding.UTF8
553+
554+
disposables.Register(
555+
{ new IDisposable with
556+
member _.Dispose() =
557+
Console.OutputEncoding <- previousEncoding
558+
}
559+
)
560+
553561
// Display the banner text, if necessary
554562
if not bannerAlreadyPrinted then
555563
Console.Write(GetBannerText tcConfigB)
@@ -1242,16 +1250,6 @@ let CompileFromCommandLineArguments
12421250
) =
12431251

12441252
use disposables = new DisposablesTracker()
1245-
let savedOut = Console.Out
1246-
1247-
use _ =
1248-
{ new IDisposable with
1249-
member _.Dispose() =
1250-
try
1251-
Console.SetOut(savedOut)
1252-
with _ ->
1253-
()
1254-
}
12551253

12561254
main1 (
12571255
ctok,

src/Compiler/Interactive/fsi.fs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -846,7 +846,7 @@ type internal FsiStdinSyphon(errorWriter: TextWriter) =
846846
/// Encapsulates functions used to write to outWriter and errorWriter
847847
type internal FsiConsoleOutput(tcConfigB, outWriter: TextWriter, errorWriter: TextWriter) =
848848

849-
let nullOut = new StreamWriter(Stream.Null) :> TextWriter
849+
let nullOut = TextWriter.Null
850850

851851
let fprintfnn (os: TextWriter) fmt =
852852
Printf.kfprintf
@@ -1203,11 +1203,6 @@ type internal FsiCommandLineOptions(fsi: FsiEvaluationSessionHostConfig, argv: s
12031203
if tcConfigB.clearResultsCache then
12041204
dependencyProvider.ClearResultsCache(tcConfigB.compilerToolPaths, getOutputDir tcConfigB, reportError rangeCmdArgs)
12051205

1206-
if tcConfigB.utf8output then
1207-
let prev = Console.OutputEncoding
1208-
Console.OutputEncoding <- Encoding.UTF8
1209-
System.AppDomain.CurrentDomain.ProcessExit.Add(fun _ -> Console.OutputEncoding <- prev)
1210-
12111206
do
12121207
let firstArg =
12131208
match sourceFiles with
@@ -4646,6 +4641,20 @@ type FsiEvaluationSession
46464641
with e ->
46474642
warning (e)
46484643

4644+
let restoreEncoding =
4645+
if tcConfigB.utf8output && Console.OutputEncoding <> Text.Encoding.UTF8 then
4646+
let previousEncoding = Console.OutputEncoding
4647+
Console.OutputEncoding <- Encoding.UTF8
4648+
4649+
Some(
4650+
{ new IDisposable with
4651+
member _.Dispose() =
4652+
Console.OutputEncoding <- previousEncoding
4653+
}
4654+
)
4655+
else
4656+
None
4657+
46494658
do
46504659
updateBannerText () // resetting banner text after parsing options
46514660

@@ -4789,6 +4798,7 @@ type FsiEvaluationSession
47894798
member _.Dispose() =
47904799
(tcImports :> IDisposable).Dispose()
47914800
uninstallMagicAssemblyResolution.Dispose()
4801+
restoreEncoding |> Option.iter (fun x -> x.Dispose())
47924802

47934803
/// Load the dummy interaction, load the initial files, and,
47944804
/// if interacting, start the background thread to read the standard input.

src/Compiler/Service/service.fs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,14 +100,6 @@ module CompileHelpers =
100100

101101
diagnostics.ToArray(), result
102102

103-
let setOutputStreams execute =
104-
// Set the output streams, if requested
105-
match execute with
106-
| Some(writer, error) ->
107-
Console.SetOut writer
108-
Console.SetError error
109-
| None -> ()
110-
111103
[<Sealed; AutoSerializable(false)>]
112104
// There is typically only one instance of this type in an IDE process.
113105
type FSharpChecker

src/fsi/fsimain.fs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -358,16 +358,6 @@ let evaluateSession (argv: string[]) =
358358
let MainMain argv =
359359
ignore argv
360360
let argv = System.Environment.GetCommandLineArgs()
361-
let savedOut = Console.Out
362-
363-
use __ =
364-
{ new IDisposable with
365-
member _.Dispose() =
366-
try
367-
Console.SetOut(savedOut)
368-
with _ ->
369-
()
370-
}
371361

372362
let timesFlag = argv |> Array.exists (fun x -> x = "/times" || x = "--times")
373363

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
2+
3+
namespace CompilerOptions.Fsc
4+
5+
open Xunit
6+
open FSharp.Test
7+
open FSharp.Test.Compiler
8+
open System
9+
10+
module utf8output =
11+
12+
[<Fact>]
13+
let ``OutputEncoding is restored after executing compilation`` () =
14+
let currentEncoding = Console.OutputEncoding
15+
use restoreCurrentEncodingAfterTest = { new IDisposable with member _.Dispose() = Console.OutputEncoding <- currentEncoding }
16+
17+
// UTF16
18+
let encoding = Text.Encoding.Unicode
19+
20+
Console.OutputEncoding <- encoding
21+
22+
Fs """printfn "Hello world" """
23+
|> asExe
24+
|> withOptionsString "--utf8output"
25+
|> compile
26+
|> shouldSucceed
27+
|> ignore
28+
29+
Console.OutputEncoding.BodyName |> Assert.shouldBe encoding.BodyName
30+
31+
[<Fact>]
32+
let ``OutputEncoding is restored after running script`` () =
33+
let currentEncoding = Console.OutputEncoding
34+
use restoreCurrentEncodingAfterTest = { new IDisposable with member _.Dispose() = Console.OutputEncoding <- currentEncoding }
35+
36+
// UTF16
37+
let encoding = Text.Encoding.Unicode
38+
39+
Console.OutputEncoding <- encoding
40+
41+
Fsx """printfn "Hello world" """
42+
|> withOptionsString "--utf8output"
43+
|> runFsi
44+
|> shouldSucceed
45+
|> ignore
46+
47+
Console.OutputEncoding.BodyName |> Assert.shouldBe encoding.BodyName

tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@
288288
<Compile Include="CompilerOptions\fsc\highentropyva.fs" />
289289
<Compile Include="CompilerOptions\fsc\langversion.fs" />
290290
<Compile Include="CompilerOptions\fsc\misc\misc.fs" />
291+
<Compile Include="CompilerOptions\fsc\misc\utf8output.fs" />
291292
<Compile Include="CompilerOptions\fsc\noframework\noframework.fs" />
292293
<Compile Include="CompilerOptions\fsc\platform\platform.fs" />
293294
<Compile Include="CompilerOptions\fsc\times\times.fs" />

0 commit comments

Comments
 (0)