Argument Fowarding Tests should account for newline added by StreamFowarder. Add an entry to developer guide so command developers will use Console.WriteLine. PR feedback and slight refactoring.

This commit is contained in:
Bryan Thornbury 2016-02-05 12:29:16 -08:00
parent ccaaebf6e5
commit b8e95a9568
3 changed files with 39 additions and 21 deletions

View file

@ -65,3 +65,6 @@ Each command's project root should contain a manpage-style Readme.md that descri
#### Add command to packages
- Update the `symlinks` property of `packaging/debian/debian_config.json` to include the new command
- Update the `$Projects` property in `packaging/osx/scripts/postinstall`
#### Things to Know
- Any added commands are usually invoked through `dotnet {command}`. As a result of this, stdout and stderr are redirected through the driver (`dotnet`) and buffered by line. As a result of this, child commands should use Console.WriteLine in any cases where they expect output to be written immediately. Any uses of Console.Write should be followed by Console.WriteLine to ensure the output is written.

View file

@ -2,11 +2,15 @@ using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Linq;
namespace Microsoft.DotNet.Cli.Utils
{
public sealed class StreamForwarder
{
private static readonly char[] s_ignoreCharacters = new char[] { '\r' };
private static readonly char s_flushBuilderCharacter = '\n';
private StringBuilder _builder;
private StringWriter _capture;
private Action<string> _write;
@ -22,10 +26,8 @@ namespace Microsoft.DotNet.Cli.Utils
public StreamForwarder Capture()
{
if (_capture != null)
{
throw new InvalidOperationException("Already capturing stream!");
}
ThrowIfCaptureSet();
_capture = new StringWriter();
return this;
@ -33,15 +35,9 @@ namespace Microsoft.DotNet.Cli.Utils
public StreamForwarder ForwardTo(Action<string> writeLine)
{
if (writeLine == null)
{
throw new ArgumentNullException(nameof(writeLine));
}
ThrowIfNull(writeLine);
if (_writeLine != null)
{
throw new InvalidOperationException("WriteLine forwarder set previously");
}
ThrowIfForwarderSet();
_writeLine = writeLine;
@ -71,18 +67,13 @@ namespace Microsoft.DotNet.Cli.Utils
{
currentCharacter = buffer[0];
// Flush per line
if (currentCharacter == '\n')
if (currentCharacter == s_flushBuilderCharacter)
{
WriteBuilder();
}
else
else if (! s_ignoreCharacters.Contains(currentCharacter))
{
// Ignore \r
if (currentCharacter != '\r')
{
_builder.Append(currentCharacter);
}
_builder.Append(currentCharacter);
}
}
@ -114,5 +105,29 @@ namespace Microsoft.DotNet.Cli.Utils
_writeLine(str);
}
}
private void ThrowIfNull(object obj)
{
if (obj == null)
{
throw new ArgumentNullException(nameof(obj));
}
}
private void ThrowIfForwarderSet()
{
if (_writeLine != null)
{
throw new InvalidOperationException("WriteLine forwarder set previously");
}
}
private void ThrowIfCaptureSet()
{
if (_capture != null)
{
throw new InvalidOperationException("Already capturing stream!");
}
}
}
}

View file

@ -206,7 +206,7 @@ namespace Microsoft.DotNet.Tests.ArgumentForwarding
/// <returns></returns>
private string[] ParseReflectorOutput(string reflectorOutput)
{
return reflectorOutput.Split(',');
return reflectorOutput.TrimEnd('\r', '\n').Split(',');
}
/// <summary>