Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CompositeFormat.MinimumArgumentCount and remove TryParse #85348

Merged
merged 2 commits into from
Apr 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -85,31 +85,13 @@ public static CompositeFormat Parse([StringSyntax(StringSyntaxAttribute.Composit
return new CompositeFormat(format, segments.ToArray());
}

/// <summary>Try to parse the composite format string <paramref name="format"/>.</summary>
/// <param name="format">The string to parse.</param>
/// <param name="compositeFormat">The parsed <see cref="CompositeFormat"/> if parsing was successful; otherwise, null.</param>
/// <returns><see langword="true"/> the <paramref name="format"/> can be parsed successfully; otherwise, <see langword="false"/>.</returns>
public static bool TryParse([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string? format, [NotNullWhen(true)] out CompositeFormat? compositeFormat)
{
if (format is not null)
{
var segments = new List<(string? Literal, int ArgIndex, int Alignment, string? Format)>();
int failureOffset = default;
ExceptionResource failureReason = default;
if (TryParseLiterals(format, segments, ref failureOffset, ref failureReason))
{
compositeFormat = new CompositeFormat(format, segments.ToArray());
return true;
}
}

compositeFormat = null;
return false;
}

/// <summary>Gets the original composite format string used to create this <see cref="CompositeFormat"/> instance.</summary>
public string Format { get; }

/// <summary>Gets the minimum number of arguments that must be passed to a formatting operation using this <see cref="CompositeFormat"/>.</summary>
/// <remarks>It's permissible to supply more arguments than this value, but it's an error to pass fewer.</remarks>
public int MinimumArgumentCount => _argsRequired;

/// <summary>Throws an exception if the specified number of arguments is fewer than the number required.</summary>
/// <param name="numArgs">The number of arguments provided by the caller.</param>
/// <exception cref="FormatException">An insufficient number of arguments were provided.</exception>
Expand Down
2 changes: 1 addition & 1 deletion src/libraries/System.Runtime/ref/System.Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14194,8 +14194,8 @@ public sealed class CompositeFormat
{
internal CompositeFormat() { }
public static System.Text.CompositeFormat Parse([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format) { throw null; }
public static bool TryParse([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Text.CompositeFormat? compositeFormat) { throw null; }
public string Format { get { throw null; } }
public int MinimumArgumentCount { get { throw null; } }
}
public abstract partial class Decoder
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.Linq;
using Xunit;

namespace System.Text.Tests
Expand All @@ -13,9 +14,6 @@ public void NullArgument_Throws()
{
AssertExtensions.Throws<ArgumentNullException>("format", () => CompositeFormat.Parse(null));

Assert.False(CompositeFormat.TryParse(null, out CompositeFormat? compositeFormat));
Assert.Null(compositeFormat);

AssertExtensions.Throws<ArgumentNullException>("format", () => string.Format(null, (CompositeFormat)null, 0));
AssertExtensions.Throws<ArgumentNullException>("format", () => string.Format(null, (CompositeFormat)null, 0, 0));
AssertExtensions.Throws<ArgumentNullException>("format", () => string.Format(null, (CompositeFormat)null, 0, 0, 0));
Expand Down Expand Up @@ -55,6 +53,30 @@ public static void DebuggerDisplay_ShowsFormat()
Assert.Equal($"\"{format}\"", DebuggerAttributes.ValidateDebuggerDisplayReferences(cf));
}

[Theory]
[InlineData("", 0)]
[InlineData("testing 123", 0)]
[InlineData("testing {{123}}", 0)]
[InlineData("{0}", 1)]
[InlineData("{0} {1}", 2)]
[InlineData("{2}", 3)]
[InlineData("{2} {0}", 3)]
[InlineData("{1} {34} {3}", 35)]
public static void MinimumArgumentCount_MatchesExpectedValue(string format, int expected)
{
CompositeFormat cf = CompositeFormat.Parse(format);

Assert.Equal(expected, cf.MinimumArgumentCount);

string s = string.Format(null, cf, Enumerable.Repeat((object)"arg", expected).ToArray());
Assert.NotNull(s);

if (expected != 0)
{
Assert.Throws<FormatException>(() => string.Format(null, cf, Enumerable.Repeat((object)"arg", expected - 1).ToArray()));
}
}

[Theory]
[MemberData(nameof(System.Tests.StringTests.Format_Valid_TestData), MemberType = typeof(System.Tests.StringTests))]
public static void StringFormat_Valid(IFormatProvider provider, string format, object[] values, string expected)
Expand All @@ -63,10 +85,6 @@ public static void StringFormat_Valid(IFormatProvider provider, string format, o
Assert.NotNull(cf);
Assert.Same(format, cf.Format);

Assert.True(CompositeFormat.TryParse(format, out CompositeFormat? cf2));
Assert.NotNull(cf2);
Assert.Same(format, cf2.Format);

Assert.Equal(expected, string.Format(provider, cf, values));

Assert.Equal(expected, string.Format(provider, cf, (ReadOnlySpan<object?>)values));
Expand Down Expand Up @@ -95,10 +113,6 @@ public static void StringBuilderAppendFormat_Valid(IFormatProvider provider, str
Assert.NotNull(cf);
Assert.Same(format, cf.Format);

Assert.True(CompositeFormat.TryParse(format, out CompositeFormat? cf2));
Assert.NotNull(cf2);
Assert.Same(format, cf2.Format);

var sb = new StringBuilder();

Assert.Same(sb, sb.AppendFormat(provider, cf, values));
Expand Down Expand Up @@ -135,10 +149,6 @@ public static void MemoryExtensionsTryWrite_Valid(IFormatProvider provider, stri
Assert.NotNull(cf);
Assert.Same(format, cf.Format);

Assert.True(CompositeFormat.TryParse(format, out CompositeFormat? cf2));
Assert.NotNull(cf2);
Assert.Same(format, cf2.Format);

char[] dest = new char[expected.Length];
int charsWritten;

Expand Down Expand Up @@ -189,9 +199,6 @@ public static void Parse_Invalid_FormatExceptionFromFormat(IFormatProvider provi
_ = args;

Assert.Throws<FormatException>(() => CompositeFormat.Parse(format));

Assert.False(CompositeFormat.TryParse(format, out CompositeFormat? compositeFormat));
Assert.Null(compositeFormat);
}

[Theory]
Expand Down