Skip to content

Commit

Permalink
Allow nullable args in all Format methods (#196)
Browse files Browse the repository at this point in the history
* Opposed to `string.Format` null(able) arguments are allowed.
* Changes effect classes Smart and SmartFormatter
* Bump version to 3.0.0-alpha.2
  • Loading branch information
axunonb authored Sep 5, 2021
1 parent 3f68d93 commit 3188ed9
Show file tree
Hide file tree
Showing 13 changed files with 408 additions and 354 deletions.
6 changes: 5 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Latest Changes
====

What's new in v3.0.0-alpha.1
What's new in v3.0.0-alpha.2
====

### 1. Significant boost in performance
Expand Down Expand Up @@ -112,6 +112,10 @@ The nullable operator can also be used for evaluating a list index. E.g.: `Smart

**Note:** Trying to evaluate `null` without the nullable operator will result in a formatting exception. This is the same behavior as in v2.

All `Format()` methods accept nullable args (**[#196](https://github.com/axuno/SmartFormat/pull/196)**).
Opposed to `string.Format` null(able) arguments are allowed.


### 10. Added `NullFormatter` ([#176](https://github.com/axuno/SmartFormat/pull/176))

In the context of Nullable Notation, the `NullFormatter` has been added. It outputs a custom string literal, if the variable is `null`, else `string.Empty`.
Expand Down
636 changes: 322 additions & 314 deletions Dev_Diary_For_v3.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<Copyright>Copyright 2011-2021 axuno gGmbH, Scott Rippey, Bernhard Millauer and other contributors.</Copyright>
<RepositoryUrl>https://github.com/axuno/SmartFormat.git</RepositoryUrl>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<Version>3.0.0-alpha.1</Version>
<Version>3.0.0-alpha.2</Version>
<FileVersion>3.0.0</FileVersion>
<AssemblyVersion>3.0.0</AssemblyVersion> <!--only update AssemblyVersion with major releases -->
<LangVersion>latest</LangVersion>
Expand Down
15 changes: 14 additions & 1 deletion src/SmartFormat.Tests/Core/FormatterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,26 @@ public void Formatter_Pure_Literal_No_Args()
Assert.That(formatter.Format(parsed), Is.EqualTo("ABC"));
}

[Test]
public void Formatter_With_Null_Args()
{
var formatter = Smart.CreateDefaultSmartFormat();
Assert.That(formatter.Format("a{0}b{1}c", null, null), Is.EqualTo("abc"));
}

[Test]
public void Formatter_With_IList_Objects()
{
var formatter = Smart.CreateDefaultSmartFormat();
Assert.That(formatter.Format("{0}{1}", new List<object>{0,1}), Is.EqualTo("01"));
Assert.That(formatter.Format("{0}{1}", new List<object?>{0,1}), Is.EqualTo("01"));
}

[Test]
public void Formatter_With_IList_Null()
{
var formatter = Smart.CreateDefaultSmartFormat();
Assert.That(formatter.Format("a{0}{1}b", new List<object?>{null, null}), Is.EqualTo("ab"));
}

[Test]
public void Formatter_Throws_Exceptions()
Expand Down
24 changes: 24 additions & 0 deletions src/SmartFormat.Tests/Core/SmartStaticTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,30 @@ public void Smart_Format_Three_Args()
Assert.That(Smart.Format("{0} {1} {2}", "THIS","IS","SMART"), Is.EqualTo("THIS IS SMART"));
}

[Test]
public void Smart_Format_One_Null_Arg()
{
Assert.That(Smart.Format("SMART{0}", (object?) null), Is.EqualTo("SMART"));
}

[Test]
public void Smart_Format_Two_Null_Args()
{
Assert.That(Smart.Format("VERY{0} {1}SMART", null, null), Is.EqualTo("VERY SMART"));
}

[Test]
public void Smart_Format_Three_Null_Args()
{
Assert.That(Smart.Format("THIS{0} IS {1}SMART{2}", null, null, null), Is.EqualTo("THIS IS SMART"));
}

[Test]
public void Smart_Format_Param_Null_Args()
{
Assert.That(Smart.Format("THIS{0} IS {1}SMART{2}{3}", null, null, null, null), Is.EqualTo("THIS IS SMART"));
}

[Test]
public void Smart_Format_With_FormatProvider()
{
Expand Down
4 changes: 2 additions & 2 deletions src/SmartFormat.Tests/Extensions/DefaultSourceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ private class SourceImplementation : Source
public void Call_With_NonNumeric_Argument_Should_Fail()
{
var source = new DefaultSource();
Assert.That(source.TryEvaluateSelector(FormattingInfo.Create("{a}", new List<object>())), Is.EqualTo(false));
Assert.That(source.TryEvaluateSelector(FormattingInfo.Create("{a}", new List<object?>())), Is.EqualTo(false));
}

[Test]
public void TryEvaluateSelector_Should_Fail()
{
var source = new SourceImplementation();
Assert.That(source.TryEvaluateSelector(FormattingInfo.Create("{Dummy}", new List<object>())), Is.EqualTo(false));
Assert.That(source.TryEvaluateSelector(FormattingInfo.Create("{Dummy}", new List<object?>())), Is.EqualTo(false));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public void ImplicitFormatterEvaluation_With_Wrong_Args_Should_Fail()
var smart = GetFormatter();
Assert.That(
smart.GetFormatterExtension<SubStringFormatter>()!.TryEvaluateFormat(
FormattingInfo.Create("{0::(0,2)}", new List<object>(new[] {new object()}))), Is.EqualTo(false));
FormattingInfo.Create("{0::(0,2)}", new List<object?>(new[] {new object()}))), Is.EqualTo(false));
}
}
}
4 changes: 2 additions & 2 deletions src/SmartFormat/Core/Formatting/FormatDetails.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class FormatDetails
/// <param name="originalArgs">The original set of arguments passed to the format method.</param>
/// <param name="provider">The <see cref="IFormatProvider"/> that can be used to determine how to format items.</param>
/// <param name="output">The <see cref="IOutput"/> where the result is written.</param>
public FormatDetails(SmartFormatter formatter, Format originalFormat, IList<object> originalArgs,
public FormatDetails(SmartFormatter formatter, Format originalFormat, IList<object?> originalArgs,
IFormatProvider? provider, IOutput output)
{
Formatter = formatter;
Expand All @@ -50,7 +50,7 @@ public FormatDetails(SmartFormatter formatter, Format originalFormat, IList<obje
/// The original set of arguments passed to the format method.
/// These provide global-access to the original arguments.
/// </summary>
public IList<object> OriginalArgs { get; }
public IList<object?> OriginalArgs { get; }

/// <summary>
/// The <see cref="IFormatProvider"/> that can be used to determine how to
Expand Down
2 changes: 1 addition & 1 deletion src/SmartFormat/Core/Formatting/FormattingInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ private void PostAlign(int textLength)
/// <param name="format">The input format string.</param>
/// <param name="data">The data argument.</param>
/// <returns>A new instance of <see cref="FormattingInfo"/>.</returns>
internal static FormattingInfo Create(string format, IList<object> data)
internal static FormattingInfo Create(string format, IList<object?> data)
{
var formatter = new SmartFormatter(new SmartSettings());
var formatParsed = formatter.Parser.ParseFormat(format);
Expand Down
4 changes: 2 additions & 2 deletions src/SmartFormat/Core/Parsing/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ public void UseAlternativeEscapeChar(char alternativeEscapeChar = '\\')
[Obsolete("Use 'Settings.StringFormatCompatibility' instead.", true)]
public void UseBraceEscaping()
{
throw new NotImplementedException($"Init-only property {nameof(Settings)}.{nameof(Settings.StringFormatCompatibility)} can only be set in an object initializer");
throw new NotSupportedException($"Init-only property {nameof(Settings)}.{nameof(Settings.StringFormatCompatibility)} can only be set in an object initializer");
}

/// <summary>
Expand All @@ -150,7 +150,7 @@ public void UseBraceEscaping()
[Obsolete("This feature has been removed", true)]
public void UseAlternativeBraces(char opening, char closing)
{
throw new NotImplementedException("This feature has been removed");
throw new NotSupportedException("This feature has been removed");
}

#endregion
Expand Down
1 change: 0 additions & 1 deletion src/SmartFormat/Extensions/DefaultSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

using SmartFormat.Core.Extensions;
using SmartFormat.Core.Parsing;
using SmartFormat.Core.Settings;

namespace SmartFormat.Extensions
{
Expand Down
24 changes: 15 additions & 9 deletions src/SmartFormat/Smart.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//

using System;
using System.Collections.Generic;
using SmartFormat.Core.Extensions;
using SmartFormat.Core.Settings;
using SmartFormat.Extensions;
Expand All @@ -25,8 +26,9 @@ public static class Smart
/// </summary>
/// <param name="format"></param>
/// <param name="args"></param>
/// <remarks>Use <see cref="Default"/> or <see cref="SmartFormatter"/> for more <i>Format(...)</i> overloads.</remarks>
/// <returns>The format items in the specified format string replaced with the string representation or the corresponding object.</returns>
public static string Format(string format, params object[] args)
public static string Format(string format, params object?[] args)
{
return Default.Format(format, args);
}
Expand All @@ -37,8 +39,9 @@ public static string Format(string format, params object[] args)
/// <param name="provider"></param>
/// <param name="format"></param>
/// <param name="args"></param>
/// <remarks>Use <see cref="Default"/> or <see cref="SmartFormatter"/> for more <i>Format(...)</i> overloads.</remarks>
/// <returns>The format items in the specified format string replaced with the string representation or the corresponding object.</returns>
public static string Format(IFormatProvider provider, string format, params object[] args)
public static string Format(IFormatProvider provider, string format, params object?[] args)
{
return Default.Format(provider, format, args);
}
Expand All @@ -54,10 +57,11 @@ public static string Format(IFormatProvider provider, string format, params obje
/// <param name="arg0"></param>
/// <param name="arg1"></param>
/// <param name="arg2"></param>
/// <remarks>Use <see cref="Default"/> or <see cref="SmartFormatter"/> for more <i>Format(...)</i> overloads.</remarks>
/// <returns>The format items in the specified format string replaced with the string representation or the corresponding object.</returns>
public static string Format(string format, object arg0, object arg1, object arg2)
public static string Format(string format, object? arg0, object? arg1, object? arg2)
{
return Format(format, new[] {arg0, arg1, arg2});
return Default.Format(format, arg0, arg1, arg2);
}

/// <summary>
Expand All @@ -66,21 +70,23 @@ public static string Format(string format, object arg0, object arg1, object arg2
/// <param name="format"></param>
/// <param name="arg0"></param>
/// <param name="arg1"></param>
/// <remarks>Use <see cref="Default"/> or <see cref="SmartFormatter"/> for more <i>Format(...)</i> overloads.</remarks>
/// <returns>The format items in the specified format string replaced with the string representation or the corresponding object.</returns>
public static string Format(string format, object arg0, object arg1)
public static string Format(string format, object? arg0, object? arg1)
{
return Format(format, new[] {arg0, arg1});
return Default.Format(format, arg0, arg1);
}

/// <summary>
/// Formats
/// </summary>
/// <param name="format"></param>
/// <param name="arg0"></param>
/// <remarks>Use <see cref="Default"/> or <see cref="SmartFormatter"/> for more <i>Format(...)</i> overloads.</remarks>
/// <returns></returns>
public static string Format(string format, object arg0)
public static string Format(string format, object? arg0)
{
return Default.Format(format, arg0); // call Default.Format in order to avoid infinite recursive method call
return Default.Format(format, arg0);
}

#endregion
Expand All @@ -90,7 +96,7 @@ public static string Format(string format, object arg0)
/// <summary>
/// Gets or sets the default <see cref="SmartFormatter"/>.
/// If not set, the <see cref="CreateDefaultSmartFormat"/> will be used.
/// It is recommended to set the <see cref="Default"/> with the extensions that are actually needed.
/// It is recommended to set the <see cref="Default"/> <see cref="SmartFormatter"/> with the extensions that are actually needed.
/// </summary>
public static SmartFormatter Default { get; set; } = CreateDefaultSmartFormat();

Expand Down
Loading

0 comments on commit 3188ed9

Please sign in to comment.