| File: Hosting\ObjectFormatter\CommonObjectFormatter.Builder.cs | Web Access |
| Project: src\roslyn\src\Scripting\Core\Microsoft.CodeAnalysis.Scripting.csproj (Microsoft.CodeAnalysis.Scripting) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System; using System.Text; namespace Microsoft.CodeAnalysis.Scripting.Hosting { /// <summary> /// Object pretty printer. /// </summary> internal abstract partial class CommonObjectFormatter { private sealed class Builder { private readonly StringBuilder _sb; private readonly bool _suppressEllipsis; private readonly BuilderOptions _options; private int _currentLimit; public Builder(BuilderOptions options, bool suppressEllipsis) { _sb = new StringBuilder(); _suppressEllipsis = suppressEllipsis; _options = options; _currentLimit = Math.Min(_options.MaximumLineLength, _options.MaximumOutputLength); } public int Remaining { get { return _options.MaximumOutputLength - _sb.Length; } } // can be negative (the min value is -Ellipsis.Length - 1) private int CurrentRemaining { get { return _currentLimit - _sb.Length; } } public void AppendLine() { // remove line length limit so that we can insert a new line even // if the previous one hit maxed out the line limit: _currentLimit = _options.MaximumOutputLength; Append(_options.NewLine); // recalc limit for the next line: _currentLimit = (int)Math.Min((long)_sb.Length + _options.MaximumLineLength, _options.MaximumOutputLength); } private void AppendEllipsis() { if (_suppressEllipsis) { return; } var ellipsis = _options.Ellipsis; if (string.IsNullOrEmpty(ellipsis)) { return; } _sb.Append(ellipsis); } public void Append(char c, int count = 1) { if (CurrentRemaining < 0) { return; } int length = Math.Min(count, CurrentRemaining); _sb.Append(c, length); if (!_suppressEllipsis && length < count) { AppendEllipsis(); } } public void Append(string str, int start = 0, int count = Int32.MaxValue) { if (str == null || CurrentRemaining < 0) { return; } count = Math.Min(count, str.Length - start); int length = Math.Min(count, CurrentRemaining); _sb.Append(str, start, length); if (!_suppressEllipsis && length < count) { AppendEllipsis(); } } public void AppendFormat(string format, params object[] args) { Append(string.Format(format, args)); } public void AppendGroupOpening() { Append('{'); } public void AppendGroupClosing(bool inline) { if (inline) { Append(" }"); } else { AppendLine(); Append('}'); AppendLine(); } } public void AppendCollectionItemSeparator(bool isFirst, bool inline) { if (isFirst) { if (inline) { Append(' '); } else { AppendLine(); } } else { if (inline) { Append(", "); } else { Append(','); AppendLine(); } } if (!inline) { Append(_options.Indentation); } } /// <remarks> /// This is for conveying cyclic dependencies to the user, not for detecting them. /// </remarks> internal void AppendInfiniteRecursionMarker() { AppendGroupOpening(); AppendCollectionItemSeparator(isFirst: true, inline: true); Append("..."); AppendGroupClosing(inline: true); } public override string ToString() { return _sb.ToString(); } } } }