提交 109795e1 编写于 作者: J Jared Parsons

Change how we do UTF8 output

Both compilers support the /utf8output flag to change the output
encoding to UTF8.  The implementation was using Console.OutputEncoding
which is not supported in CoreFx.  Changed the implementation to use the
supported API pairs of OpenStandard* and Set*.

Note: The compiler was also using IsOutputRedirected which isn't
supported on CoreFx and has no portable replacement.  After discussion
with the compiler team we decided to omit this check.  It a check that
is more aimed at preventing the user from making a mistake by not
redirecting the output vs. enforcing an actual constraint.

closes #1970
上级 12bdab4c
......@@ -6,6 +6,7 @@
using System.Reflection;
using System.Text;
using Microsoft.VisualStudio.Shell.Interop;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.CommandLine
{
......@@ -23,28 +24,7 @@ internal static int Run(string clientDir, string sdkDirectory, string[] args)
var responseFile = Path.Combine(clientDir, CSharpCompiler.ResponseFileName);
Csc compiler = new Csc(responseFile, Directory.GetCurrentDirectory(), sdkDirectory, args);
// We store original encoding and restore it later to revert
// the changes that might be done by /utf8output options
// NOTE: original encoding may not be restored if process terminated
Encoding origEncoding = Console.OutputEncoding;
try
{
if (compiler.Arguments.Utf8Output && Console.IsOutputRedirected)
{
Console.OutputEncoding = Encoding.UTF8;
}
return compiler.Run(Console.Out);
}
finally
{
try
{
Console.OutputEncoding = origEncoding;
}
catch
{ // Try to reset the output encoding, ignore if we can't
}
}
return ConsoleUtil.RunWithOutput(compiler.Arguments.Utf8Output, (textWriterOut, _) => compiler.Run(textWriterOut));
}
public override Assembly LoadAssembly(string fullPath)
......
......@@ -82,6 +82,9 @@
<Compile Include="..\..\Core\VBCSCompiler\CompilerServerLogger.cs">
<Link>CompilerServerLogger.cs</Link>
</Compile>
<Compile Include="..\..\Helpers\ConsoleUtil.cs">
<Link>ConsoleUtil.cs</Link>
</Compile>
<Compile Include="Csc.cs" />
<Compile Include="Program.cs" />
</ItemGroup>
......@@ -102,4 +105,4 @@
<Import Project="..\..\..\..\build\VSL.Imports.Closed.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
</ImportGroup>
</Project>
\ No newline at end of file
</Project>
......@@ -16,6 +16,7 @@
using static Microsoft.CodeAnalysis.BuildTasks.NativeMethods;
using static Microsoft.CodeAnalysis.CompilerServer.BuildProtocolConstants;
using static Microsoft.CodeAnalysis.CompilerServer.CompilerServerLogger;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.BuildTasks
{
......@@ -86,27 +87,14 @@ private static int HandleResponse(BuildResponse response)
if (response.Type == BuildResponse.ResponseType.Completed)
{
var completedResponse = (CompletedBuildResponse)response;
var origEncoding = Console.OutputEncoding;
try
{
if (completedResponse.Utf8Output && Console.IsOutputRedirected)
{
Console.OutputEncoding = Encoding.UTF8;
}
Console.Out.Write(completedResponse.Output);
Console.Error.Write(completedResponse.ErrorOutput);
}
finally
{
try
return ConsoleUtil.RunWithOutput(
completedResponse.Utf8Output,
(outWriter, errorWriter) =>
{
Console.OutputEncoding = origEncoding;
}
catch
{ // Try to reset the output encoding, ignore if we can't
}
}
return completedResponse.ReturnCode;
outWriter.Write(completedResponse.Output);
errorWriter.Write(completedResponse.ErrorOutput);
return completedResponse.ReturnCode;
});
}
else
{
......
......@@ -51,6 +51,9 @@
<Compile Include="..\VBCSCompiler\CompilerServerLogger.cs">
<Link>CompilerServerLogger.cs</Link>
</Compile>
<Compile Include="..\..\Helpers\ConsoleUtil.cs">
<Link>ConsoleUtil.cs</Link>
</Compile>
<Compile Include="BuildClient.cs" />
<Compile Include="CanonicalError.cs" />
<Compile Include="CommandLineBuilderExtension.cs" />
......@@ -94,4 +97,4 @@
<Import Project="..\..\..\Tools\Microsoft.CodeAnalysis.Toolset.Open\Targets\VSL.Imports.targets" />
<Import Project="..\..\..\..\build\VSL.Imports.Closed.targets" />
</ImportGroup>
</Project>
\ No newline at end of file
</Project>
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.CodeAnalysis;
using System;
using System.IO;
using System.Text;
namespace Roslyn.Utilities
{
internal static class ConsoleUtil
{
private static readonly Encoding s_utf8Encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
/// <summary>
/// When <paramref name="utf8Encoding"/> is true then <paramref name="func"/> will be run
/// while both <see cref="Console.Out"/> and <see cref="Console.Error"/> are set
/// to set to UTF8 encoding. Otherwise it will be run with the <see cref="Console"/> in
/// its current state.
/// </summary>
internal static T RunWithOutput<T>(bool utf8Encoding, Func<TextWriter, TextWriter, T> func)
{
return utf8Encoding
? RunWithEncoding(s_utf8Encoding, func)
: func(Console.Out, Console.Error);
}
/// <summary>
/// Run the <paramref name="func"/> argument while both <see cref="Console.Out"/> and
/// <see cref="Console.Error"/> are set to set to <paramref name="encoding"/>
/// </summary>
internal static T RunWithEncoding<T>(Encoding encoding, Func<TextWriter, TextWriter, T> func)
{
TextWriter savedOut = Console.Out;
TextWriter savedError = Console.Error;
try
{
using (var streamWriterOut = new StreamWriter(Console.OpenStandardOutput(), encoding))
using (var streamWriterError = new StreamWriter(Console.OpenStandardError(), encoding))
{
Console.SetOut(streamWriterOut);
Console.SetError(streamWriterError);
return func(streamWriterOut, streamWriterError);
}
}
finally
{
try
{
Console.SetOut(savedOut);
}
catch
{
// Nothing to do if we can't reset the console.
}
try
{
Console.SetError(savedOut);
}
catch
{
// Nothing to do if we can't reset the console.
}
}
}
}
}
......@@ -4,9 +4,8 @@
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using Microsoft.VisualStudio.Shell.Interop;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.VisualBasic.CommandLine
{
......@@ -24,28 +23,7 @@ internal static int Run(string clientDir, string sdkDirectory, string[] args)
var responseFile = Path.Combine(clientDir, VisualBasicCompiler.ResponseFileName);
Vbc compiler = new Vbc(responseFile, Directory.GetCurrentDirectory(), sdkDirectory, args);
// We store original encoding and restore it later to revert
// the changes that might be done by /utf8output options
// NOTE: original encoding may not be restored if process terminated
Encoding origEncoding = Console.OutputEncoding;
try
{
if (compiler.Arguments.Utf8Output && Console.IsOutputRedirected)
{
Console.OutputEncoding = Encoding.UTF8;
}
return compiler.Run(Console.Out, default(CancellationToken));
}
finally
{
try
{
Console.OutputEncoding = origEncoding;
}
catch
{ // Try to reset the output encoding, ignore if we can't
}
}
return ConsoleUtil.RunWithOutput(compiler.Arguments.Utf8Output, (textWriterOut, _) => compiler.Run(textWriterOut));
}
public override Assembly LoadAssembly(string fullPath)
......
......@@ -82,6 +82,9 @@
<Compile Include="..\..\Core\VBCSCompiler\CompilerServerLogger.cs">
<Link>CompilerServerLogger.cs</Link>
</Compile>
<Compile Include="..\..\Helpers\ConsoleUtil.cs">
<Link>ConsoleUtil.cs</Link>
</Compile>
<Compile Include="Vbc.cs" />
<Compile Include="Program.cs" />
</ItemGroup>
......@@ -101,4 +104,4 @@
<Import Project="..\..\..\..\build\VSL.Imports.Closed.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
</ImportGroup>
</Project>
\ No newline at end of file
</Project>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册