diff --git a/src/Microsoft.Diagnostics.DebugServices.Implementation/CaptureConsoleService.cs b/src/Microsoft.Diagnostics.DebugServices.Implementation/CaptureConsoleService.cs index 7fbedebeea..19975b6989 100644 --- a/src/Microsoft.Diagnostics.DebugServices.Implementation/CaptureConsoleService.cs +++ b/src/Microsoft.Diagnostics.DebugServices.Implementation/CaptureConsoleService.cs @@ -22,22 +22,29 @@ public sealed class CaptureConsoleService : IConsoleService #region IConsoleService - public void Write(string text) => _charToLineConverter.Input(text); - - public void WriteWarning(string text) => _charToLineConverter.Input(text); - - public void WriteError(string text) => _charToLineConverter.Input(text); - - public bool SupportsDml => false; - - public void WriteDml(string text) => throw new NotSupportedException(); - - public void WriteDmlExec(string text, string _) => throw new NotSupportedException(); - - public CancellationToken CancellationToken { get; set; } = CancellationToken.None; + bool IConsoleService.SupportsDml => false; int IConsoleService.WindowWidth => int.MaxValue; + CancellationToken IConsoleService.CancellationToken { get; set; } = CancellationToken.None; + + void IConsoleService.WriteString(OutputType type, string text) + { + switch (type) + { + case OutputType.Normal: + case OutputType.Warning: + case OutputType.Error: + _charToLineConverter.Input(text); + break; + case OutputType.Dml: + throw new NotSupportedException(); + case OutputType.Logging: + default: + break; + } + } + #endregion } } diff --git a/src/Microsoft.Diagnostics.DebugServices.Implementation/CharToLineConverter.cs b/src/Microsoft.Diagnostics.DebugServices.Implementation/CharToLineConverter.cs deleted file mode 100644 index ca6e2b0690..0000000000 --- a/src/Microsoft.Diagnostics.DebugServices.Implementation/CharToLineConverter.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Text; - -namespace Microsoft.Diagnostics.DebugServices.Implementation -{ - public sealed class CharToLineConverter - { - private readonly Action m_callback; - private readonly StringBuilder m_text = new(); - - public CharToLineConverter(Action callback) - { - m_callback = callback; - } - - public void Input(byte[] buffer, int offset, int count) - { - for (int i = 0; i < count; i++) - { - char c = (char)buffer[offset + i]; - if (c == '\r') - { - continue; - } - if (c == '\n') - { - Flush(); - } - else if (c is '\t' or >= ((char)0x20) and <= ((char)127)) - { - m_text.Append(c); - } - } - } - - public void Input(string text) - { - foreach (char c in text) - { - if (c == '\r') - { - continue; - } - if (c == '\n') - { - Flush(); - } - else if (c is '\t' or >= ((char)0x20) and <= ((char)127)) - { - m_text.Append(c); - } - } - } - - public void Flush() - { - m_callback(m_text.ToString()); - m_text.Clear(); - } - } -} diff --git a/src/Microsoft.Diagnostics.DebugServices.Implementation/FileLoggingConsoleService.cs b/src/Microsoft.Diagnostics.DebugServices.Implementation/FileLoggingConsoleService.cs index 2c60c6d0cd..eaa564f116 100644 --- a/src/Microsoft.Diagnostics.DebugServices.Implementation/FileLoggingConsoleService.cs +++ b/src/Microsoft.Diagnostics.DebugServices.Implementation/FileLoggingConsoleService.cs @@ -95,93 +95,34 @@ public void RemoveStream(Stream stream) #region IConsoleService - public void Write(string text) - { - _consoleService.Write(text); - foreach (StreamWriter writer in _writers) - { - try - { - writer.Write(text); - } - catch (Exception ex) when (ex is IOException or ObjectDisposedException or NotSupportedException) - { - } - } - } - - public void WriteWarning(string text) - { - _consoleService.WriteWarning(text); - foreach (StreamWriter writer in _writers) - { - try - { - writer.Write(text); - } - catch (Exception ex) when (ex is IOException or ObjectDisposedException or NotSupportedException) - { - } - } - } - - public void WriteError(string text) - { - _consoleService.WriteError(text); - foreach (StreamWriter writer in _writers) - { - try - { - writer.Write(text); - } - catch (Exception ex) when (ex is IOException or ObjectDisposedException or NotSupportedException) - { - } - } - } - public bool SupportsDml => _consoleService.SupportsDml; - public void WriteDml(string text) + public int WindowWidth => _consoleService.WindowWidth; + + public CancellationToken CancellationToken { - _consoleService.WriteDml(text); - foreach (StreamWriter writer in _writers) - { - try - { - // TODO: unwrap the DML? - writer.Write(text); - } - catch (Exception ex) when (ex is IOException or ObjectDisposedException or NotSupportedException) - { - } - } + get { return _consoleService.CancellationToken; } + set { _consoleService.CancellationToken = value; } } - public void WriteDmlExec(string text, string action) + public void WriteString(OutputType type, string text) { - _consoleService.WriteDmlExec(text, action); - - foreach (StreamWriter writer in _writers) + _consoleService.WriteString(type, text); + if (type != OutputType.Dml) { - try - { - writer.Write(text); - } - catch (Exception ex) when (ex is IOException or ObjectDisposedException or NotSupportedException) + foreach (StreamWriter writer in _writers) { + try + { + writer.Write(text); + } + catch (Exception ex) when (ex is IOException or ObjectDisposedException or NotSupportedException) + { + } } } } - public CancellationToken CancellationToken - { - get { return _consoleService.CancellationToken; } - set { _consoleService.CancellationToken = value; } - } - - public int WindowWidth => _consoleService.WindowWidth; - #endregion } } diff --git a/src/Microsoft.Diagnostics.Repl/CharToLineConverter.cs b/src/Microsoft.Diagnostics.DebugServices/CharToLineConverter.cs similarity index 93% rename from src/Microsoft.Diagnostics.Repl/CharToLineConverter.cs rename to src/Microsoft.Diagnostics.DebugServices/CharToLineConverter.cs index 611a1cf9cd..d046e06501 100644 --- a/src/Microsoft.Diagnostics.Repl/CharToLineConverter.cs +++ b/src/Microsoft.Diagnostics.DebugServices/CharToLineConverter.cs @@ -1,10 +1,10 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Text; -namespace Microsoft.Diagnostics.Repl +namespace Microsoft.Diagnostics.DebugServices { public sealed class CharToLineConverter { diff --git a/src/Microsoft.Diagnostics.DebugServices/CommandBase.cs b/src/Microsoft.Diagnostics.DebugServices/CommandBase.cs index 7a1cf6842d..36443dcb76 100644 --- a/src/Microsoft.Diagnostics.DebugServices/CommandBase.cs +++ b/src/Microsoft.Diagnostics.DebugServices/CommandBase.cs @@ -52,7 +52,7 @@ protected void WriteLine() /// line message protected void WriteLine(string message) { - Console.Write(message + Environment.NewLine); + Console.WriteLine(message); Console.CancellationToken.ThrowIfCancellationRequested(); } @@ -63,7 +63,7 @@ protected void WriteLine(string message) /// arguments protected void WriteLine(string format, params object[] args) { - Console.Write(string.Format(format, args) + Environment.NewLine); + Console.WriteLine(format, args); Console.CancellationToken.ThrowIfCancellationRequested(); } @@ -74,7 +74,7 @@ protected void WriteLine(string format, params object[] args) /// arguments protected void WriteLineWarning(string format, params object[] args) { - Console.WriteWarning(string.Format(format, args) + Environment.NewLine); + Console.WriteLineWarning(format, args); Console.CancellationToken.ThrowIfCancellationRequested(); } @@ -85,7 +85,7 @@ protected void WriteLineWarning(string format, params object[] args) /// arguments protected void WriteLineError(string format, params object[] args) { - Console.WriteError(string.Format(format, args) + Environment.NewLine); + Console.WriteLineError(format, args); Console.CancellationToken.ThrowIfCancellationRequested(); } diff --git a/src/Microsoft.Diagnostics.DebugServices/ConsoleServiceExtensions.cs b/src/Microsoft.Diagnostics.DebugServices/ConsoleServiceExtensions.cs index e226cd0688..ef8714a281 100644 --- a/src/Microsoft.Diagnostics.DebugServices/ConsoleServiceExtensions.cs +++ b/src/Microsoft.Diagnostics.DebugServices/ConsoleServiceExtensions.cs @@ -2,61 +2,76 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Xml.Linq; namespace Microsoft.Diagnostics.DebugServices { public static class ConsoleServiceExtensions { + /// + /// Write text to console's standard out + /// + public static void Write(this IConsoleService console, string text) => console.WriteString(OutputType.Normal, text); + /// /// Display a blank line /// - /// - public static void WriteLine(this IConsoleService console) - { - console.Write(Environment.NewLine); - } + public static void WriteLine(this IConsoleService console) => console.WriteString(OutputType.Normal, Environment.NewLine); /// /// Display text /// - /// console service instance - /// text message - public static void WriteLine(this IConsoleService console, string message) - { - console.Write(message + Environment.NewLine); - } + public static void WriteLine(this IConsoleService console, string text) => console.WriteString(OutputType.Normal, text + Environment.NewLine); /// /// Display formatted text /// - /// console service instance - /// format string - /// arguments - public static void WriteLine(this IConsoleService console, string format, params object[] args) - { - console.Write(string.Format(format, args) + Environment.NewLine); - } + public static void WriteLine(this IConsoleService console, string format, params object[] args) => console.WriteString(OutputType.Normal, string.Format(format, args) + Environment.NewLine); + + /// + /// Write warning text to console + /// + public static void WriteWarning(this IConsoleService console, string text) => console.WriteString(OutputType.Warning, text); /// /// Display formatted warning text /// - /// console service instance - /// format string - /// arguments - public static void WriteLineWarning(this IConsoleService console, string format, params object[] args) - { - console.WriteWarning(string.Format(format, args) + Environment.NewLine); - } + public static void WriteLineWarning(this IConsoleService console, string format, params object[] args) => console.WriteString(OutputType.Warning, string.Format(format, args) + Environment.NewLine); + + /// + /// Write error text to console + /// + public static void WriteError(this IConsoleService console, string text) => console.WriteString(OutputType.Error, text); /// /// Display formatted error text /// + public static void WriteLineError(this IConsoleService console, string format, params object[] args) => console.WriteString(OutputType.Error, string.Format(format, args) + Environment.NewLine); + + /// + /// Writes Debugger Markup Language (DML) markup text + /// + public static void WriteDml(this IConsoleService console, string text) => console.WriteString(OutputType.Dml, text); + + /// + /// Writes an exec tag to the output stream. + /// /// console service instance - /// format string - /// arguments - public static void WriteLineError(this IConsoleService console, string format, params object[] args) + /// The display text. + /// The action to perform. + public static void WriteDmlExec(this IConsoleService console, string text, string cmd) { - console.WriteError(string.Format(format, args) + Environment.NewLine); + if (!console.SupportsDml || string.IsNullOrWhiteSpace(cmd)) + { + console.WriteString(OutputType.Normal, text); + } + else + { + string dml = $"{DmlEscape(text)}"; + console.WriteString(OutputType.Dml, dml); + } } + + private static string DmlEscape(string text) => string.IsNullOrWhiteSpace(text) ? text : new XText(text).ToString(); } } diff --git a/src/Microsoft.Diagnostics.DebugServices/IConsoleService.cs b/src/Microsoft.Diagnostics.DebugServices/IConsoleService.cs index 426e328c1b..42196864fb 100644 --- a/src/Microsoft.Diagnostics.DebugServices/IConsoleService.cs +++ b/src/Microsoft.Diagnostics.DebugServices/IConsoleService.cs @@ -11,35 +11,14 @@ namespace Microsoft.Diagnostics.DebugServices public interface IConsoleService { /// - /// Write text to console's standard out + /// Gets whether is supported. /// - /// text - void Write(string value); - - /// - /// Write warning text to console - /// - /// - void WriteWarning(string value); - - /// - /// Write error text to console - /// - /// - void WriteError(string value); - - /// Writes Debugger Markup Language (DML) markup text. - void WriteDml(string text); + bool SupportsDml { get; } /// - /// Writes an exec tag to the output stream. + /// Screen or window width or 0. /// - /// The display text. - /// The action to perform. - void WriteDmlExec(string text, string action); - - /// Gets whether is supported. - bool SupportsDml { get; } + int WindowWidth { get; } /// /// Cancellation token for current command @@ -47,8 +26,10 @@ public interface IConsoleService CancellationToken CancellationToken { get; set; } /// - /// Screen or window width or 0. + /// Writes text to the console /// - int WindowWidth { get; } + /// type of text to write + /// text to write + void WriteString(OutputType type, string text); } } diff --git a/src/Microsoft.Diagnostics.DebugServices/OutputType.cs b/src/Microsoft.Diagnostics.DebugServices/OutputType.cs new file mode 100644 index 0000000000..bfdc878a83 --- /dev/null +++ b/src/Microsoft.Diagnostics.DebugServices/OutputType.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Diagnostics.DebugServices +{ + public enum OutputType + { + Normal = 0, + Error = 1, + Warning = 2, + Logging = 3, // Used when logging to console is enabled. Allows the command output capture to ignore SOS logging output. + Dml = 4, // throws NotSupportedException if DML isn't supported or enabled. + }; +} diff --git a/src/Microsoft.Diagnostics.ExtensionCommands/Output/TextWriterConsole.cs b/src/Microsoft.Diagnostics.ExtensionCommands/Output/TextWriterConsole.cs index 92ada49058..d9c345df4a 100644 --- a/src/Microsoft.Diagnostics.ExtensionCommands/Output/TextWriterConsole.cs +++ b/src/Microsoft.Diagnostics.ExtensionCommands/Output/TextWriterConsole.cs @@ -23,20 +23,27 @@ public TextWriterConsole(TextWriter writer, CancellationToken cancellationToken) CancellationToken = cancellationToken; } - public void Write(string value) => _writer.Write(value); - - public void WriteWarning(string value) => _writer.Write(value); - - public void WriteError(string value) => _writer.Write(value); - public bool SupportsDml => false; - public void WriteDml(string text) => throw new NotSupportedException(); - - public void WriteDmlExec(string text, string action) => throw new NotSupportedException(); - public CancellationToken CancellationToken { get; set; } public int WindowWidth => int.MaxValue; + + void IConsoleService.WriteString(OutputType type, string text) + { + switch (type) + { + case OutputType.Normal: + case OutputType.Warning: + case OutputType.Error: + _writer.Write(text); + break; + case OutputType.Dml: + throw new NotSupportedException(); + case OutputType.Logging: + default: + break; + } + } } } diff --git a/src/Microsoft.Diagnostics.Repl/ConsoleService.cs b/src/Microsoft.Diagnostics.Repl/ConsoleService.cs index 9ea97a068f..c1720ad643 100644 --- a/src/Microsoft.Diagnostics.Repl/ConsoleService.cs +++ b/src/Microsoft.Diagnostics.Repl/ConsoleService.cs @@ -189,11 +189,13 @@ public void WriteLine(OutputType type, string format, params object[] parameters /// output type /// text /// ctrl-c interrupted the command + /// thrown if OutputType.Dml public void WriteOutput(OutputType type, string message) { switch (type) { case OutputType.Normal: + case OutputType.Logging: m_consoleConverter.Input(message); break; @@ -204,6 +206,9 @@ public void WriteOutput(OutputType type, string message) case OutputType.Error: m_errorConverter.Input(message); break; + + case OutputType.Dml: + throw new NotSupportedException(); } } @@ -601,20 +606,8 @@ private void EnsureNewEntry() #region IConsoleService - void IConsoleService.Write(string text) => WriteOutput(OutputType.Normal, text); - - void IConsoleService.WriteWarning(string text) => WriteOutput(OutputType.Warning, text); - - void IConsoleService.WriteError(string text) => WriteOutput(OutputType.Error, text); - bool IConsoleService.SupportsDml => false; - void IConsoleService.WriteDml(string text) => WriteOutput(OutputType.Normal, text); - - void IConsoleService.WriteDmlExec(string text, string _) => WriteOutput(OutputType.Normal, text); - - CancellationToken IConsoleService.CancellationToken { get; set; } - int IConsoleService.WindowWidth { get @@ -630,6 +623,10 @@ int IConsoleService.WindowWidth } } + CancellationToken IConsoleService.CancellationToken { get; set; } + + void IConsoleService.WriteString(OutputType type, string text) => WriteOutput(type, text); + #endregion } } diff --git a/src/Microsoft.Diagnostics.Repl/OutputType.cs b/src/Microsoft.Diagnostics.Repl/OutputType.cs deleted file mode 100644 index 3a37ad67b4..0000000000 --- a/src/Microsoft.Diagnostics.Repl/OutputType.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace Microsoft.Diagnostics.Repl -{ - /// - /// The type of output. - /// - public enum OutputType - { - Normal = 1, - Error = 2, - Warning = 3, - } -} diff --git a/src/Microsoft.Diagnostics.TestHelpers/LoggingListener.cs b/src/Microsoft.Diagnostics.TestHelpers/LoggingListener.cs index 991325b862..fec17026bd 100644 --- a/src/Microsoft.Diagnostics.TestHelpers/LoggingListener.cs +++ b/src/Microsoft.Diagnostics.TestHelpers/LoggingListener.cs @@ -3,7 +3,7 @@ using System; using System.Diagnostics; -using Microsoft.Diagnostics.DebugServices.Implementation; +using Microsoft.Diagnostics.DebugServices; using Xunit.Abstractions; namespace Microsoft.Diagnostics.TestHelpers diff --git a/src/SOS/SOS.Extensions/ConsoleServiceFromDebuggerServices.cs b/src/SOS/SOS.Extensions/ConsoleServiceFromDebuggerServices.cs index 77bc7744e3..346a4e8dae 100644 --- a/src/SOS/SOS.Extensions/ConsoleServiceFromDebuggerServices.cs +++ b/src/SOS/SOS.Extensions/ConsoleServiceFromDebuggerServices.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Threading; using System.Xml.Linq; using Microsoft.Diagnostics.DebugServices; @@ -20,33 +21,33 @@ public ConsoleServiceFromDebuggerServices(DebuggerServices debuggerServices) #region IConsoleService - public void Write(string text) => _debuggerServices.OutputString(DEBUG_OUTPUT.NORMAL, text); - - public void WriteWarning(string text) => _debuggerServices.OutputString(DEBUG_OUTPUT.WARNING, text); + public bool SupportsDml => _supportsDml ??= _debuggerServices.SupportsDml; - public void WriteError(string text) => _debuggerServices.OutputString(DEBUG_OUTPUT.ERROR, text); + public CancellationToken CancellationToken { get; set; } - public void WriteDml(string text) => _debuggerServices.OutputDmlString(DEBUG_OUTPUT.NORMAL, text); + int IConsoleService.WindowWidth => _debuggerServices.GetOutputWidth(); - public void WriteDmlExec(string text, string cmd) + void IConsoleService.WriteString(OutputType type, string text) { - if (!SupportsDml || string.IsNullOrWhiteSpace(cmd)) - { - Write(text); - } - else + switch (type) { - string dml = $"{DmlEscape(text)}"; - WriteDml(dml); + case OutputType.Normal: + _debuggerServices.OutputString(DEBUG_OUTPUT.NORMAL, text); + break; + case OutputType.Warning: + _debuggerServices.OutputString(DEBUG_OUTPUT.WARNING, text); + break; + case OutputType.Error: + _debuggerServices.OutputString(DEBUG_OUTPUT.ERROR, text); + break; + case OutputType.Dml: + _debuggerServices.OutputDmlString(DEBUG_OUTPUT.NORMAL, text); + break; + default: + throw new ArgumentOutOfRangeException(nameof(type), type, null); } } - public bool SupportsDml => _supportsDml ??= _debuggerServices.SupportsDml; - - public CancellationToken CancellationToken { get; set; } - - int IConsoleService.WindowWidth => _debuggerServices.GetOutputWidth(); - #endregion private static string DmlEscape(string text) => string.IsNullOrWhiteSpace(text) ? text : new XText(text).ToString();