Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonCropp committed Dec 14, 2023
2 parents eb23c57 + f3ce71a commit f1e0c6f
Show file tree
Hide file tree
Showing 21 changed files with 1,368 additions and 11 deletions.
4 changes: 4 additions & 0 deletions api_list.include.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@
### StringBuilder

* `StringBuilder Append(ReadOnlySpan<Char>)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.append#system-text-stringbuilder-append(system-readonlyspan((system-char))))
* `StringBuilder Append(AppendInterpolatedStringHandler&)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.append#system-text-stringbuilder-append(system-text-stringbuilder-appendinterpolatedstringhandler@))
* `StringBuilder Append(IFormatProvider, AppendInterpolatedStringHandler&)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.append#system-text-stringbuilder-append(system-iformatprovider-system-text-stringbuilder-appendinterpolatedstringhandler@))
* `StringBuilder AppendLine(AppendInterpolatedStringHandler&)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.appendline#system-text-stringbuilder-appendline(system-text-stringbuilder-appendinterpolatedstringhandler@))
* `StringBuilder AppendLine(IFormatProvider, AppendInterpolatedStringHandler&)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.appendline#system-text-stringbuilder-appendline(system-iformatprovider-system-text-stringbuilder-appendinterpolatedstringhandler@))
* `Void CopyTo(Int32, Span<Char>, Int32)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.copyto#system-text-stringbuilder-copyto(system-int32-system-span((system-char))-system-int32))
* `Boolean Equals(ReadOnlySpan<Char>)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.equals#system-text-stringbuilder-equals(system-readonlyspan((system-char))))

Expand Down
13 changes: 11 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Then all consuming projects, like tests, will not need to use the Polyfill nuget

If Polyfill is being consumed in a solution that produce a library (and usually a nuget), then the Polyfill nuget can be added to all projects.

If, however, `InternalsVisibileTo` is being used to expose APIs (for example to test projects), then the Polyfill nuget should be added only to the root library project.
If, however, `InternalsVisibleTo` is being used to expose APIs (for example to test projects), then the Polyfill nuget should be added only to the root library project.


## Included polyfills
Expand Down Expand Up @@ -283,10 +283,13 @@ static class GuardUsage

### InterpolatedStringHandler

* [AppendInterpolatedStringHandler](https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.appendinterpolatedstringhandler)
* [DefaultInterpolatedStringHandler](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.defaultinterpolatedstringhandler)
* [InterpolatedStringHandlerAttribute](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.interpolatedstringhandlerattribute)
* [InterpolatedStringHandlerArgumentAttribute](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.interpolatedstringhandlerargumentattribute)
* [ISpanFormattable](https://learn.microsoft.com/en-us/dotnet/api/system.ispanformattable)

Reference: [Write a custom string interpolation handler](https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/interpolated-string-handler)
References: [String Interpolation in C# 10 and .NET 6](https://devblogs.microsoft.com/dotnet/string-interpolation-in-c-10-and-net-6/), [Write a custom string interpolation handler](https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/interpolated-string-handler)


### StringSyntaxAttribute
Expand Down Expand Up @@ -558,9 +561,15 @@ The class `PolyfillExtensions` includes the following extension methods:
### StringBuilder

* `StringBuilder Append(ReadOnlySpan<Char>)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.append#system-text-stringbuilder-append(system-readonlyspan((system-char))))
* `StringBuilder Append(AppendInterpolatedStringHandler&)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.append#system-text-stringbuilder-append(system-text-stringbuilder-appendinterpolatedstringhandler@))
* `StringBuilder Append(IFormatProvider, AppendInterpolatedStringHandler&)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.append#system-text-stringbuilder-append(system-iformatprovider-system-text-stringbuilder-appendinterpolatedstringhandler@))
* `StringBuilder AppendLine(AppendInterpolatedStringHandler&)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.appendline#system-text-stringbuilder-appendline(system-text-stringbuilder-appendinterpolatedstringhandler@))
* `StringBuilder AppendLine(IFormatProvider, AppendInterpolatedStringHandler&)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.appendline#system-text-stringbuilder-appendline(system-iformatprovider-system-text-stringbuilder-appendinterpolatedstringhandler@))
* `Void CopyTo(Int32, Span<Char>, Int32)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.copyto#system-text-stringbuilder-copyto(system-int32-system-span((system-char))-system-int32))
* `Boolean Equals(ReadOnlySpan<Char>)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.equals#system-text-stringbuilder-equals(system-readonlyspan((system-char))))

> [!IMPORTANT]
> The methods using `AppendInterpolatedStringHandler` parameter are not extensions because the compiler prefers to use the overload with `string` parameter instead.
### CancellationToken

Expand Down
3 changes: 3 additions & 0 deletions src/Consume/Consume.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
<Compile Include="..\Polyfill\IndexRange\*.cs">
<Link>Pollyfill\IndexRange\%(RecursiveDir)%(Filename).cs</Link>
</Compile>
<Compile Include="..\Polyfill\StringInterpolation\*.cs">
<Link>Pollyfill\StringInterpolation\%(RecursiveDir)%(Filename).cs</Link>
</Compile>
<Compile Include="..\Polyfill\Trimming\*.cs">
<Link>Pollyfill\Trimming\%(RecursiveDir)%(Filename).cs</Link>
</Compile>
Expand Down
3 changes: 3 additions & 0 deletions src/ConsumeClassicReferences/ConsumeClassicReferences.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
<Compile Include="..\Polyfill\IndexRange\*.cs">
<Link>Pollyfill\IndexRange\%(RecursiveDir)%(Filename).cs</Link>
</Compile>
<Compile Include="..\Polyfill\StringInterpolation\*.cs">
<Link>Pollyfill\StringInterpolation\%(RecursiveDir)%(Filename).cs</Link>
</Compile>
<Compile Include="..\Polyfill\Trimming\*.cs">
<Link>Pollyfill\Trimming\%(RecursiveDir)%(Filename).cs</Link>
</Compile>
Expand Down
3 changes: 3 additions & 0 deletions src/ConsumeIndirect/ConsumeIndirect.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
<Compile Include="..\Polyfill\IndexRange\*.cs">
<Link>Pollyfill\IndexRange\%(RecursiveDir)%(Filename).cs</Link>
</Compile>
<Compile Include="..\Polyfill\StringInterpolation\*.cs">
<Link>Pollyfill\StringInterpolation\%(RecursiveDir)%(Filename).cs</Link>
</Compile>
<Compile Include="..\Polyfill\Trimming\*.cs">
<Link>Pollyfill\Trimming\%(RecursiveDir)%(Filename).cs</Link>
</Compile>
Expand Down
3 changes: 3 additions & 0 deletions src/ConsumeNoRefs/ConsumeNoRefs.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
<Compile Include="..\Polyfill\IndexRange\*.cs">
<Link>Pollyfill\IndexRange\%(RecursiveDir)%(Filename).cs</Link>
</Compile>
<Compile Include="..\Polyfill\StringInterpolation\*.cs">
<Link>Pollyfill\StringInterpolation\%(RecursiveDir)%(Filename).cs</Link>
</Compile>
<Compile Include="..\Polyfill\Trimming\*.cs">
<Link>Pollyfill\Trimming\%(RecursiveDir)%(Filename).cs</Link>
</Compile>
Expand Down
3 changes: 3 additions & 0 deletions src/NoRefsTests/NoRefsTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
<Compile Include="..\Polyfill\IndexRange\*.cs">
<Link>Pollyfill\IndexRange\%(RecursiveDir)%(Filename).cs</Link>
</Compile>
<Compile Include="..\Polyfill\StringInterpolation\*.cs">
<Link>Pollyfill\StringInterpolation\%(RecursiveDir)%(Filename).cs</Link>
</Compile>
<Compile Include="..\Polyfill\Trimming\*.cs">
<Link>Pollyfill\Trimming\%(RecursiveDir)%(Filename).cs</Link>
</Compile>
Expand Down
2 changes: 2 additions & 0 deletions src/Polyfill/Polyfill.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
target="contentFiles/cs/netstandard2.0/Polyfill/Nullability"/>
<file src="IndexRange\*.cs"
target="contentFiles/cs/netstandard2.0/Polyfill/IndexRange"/>
<file src="StringInterpolation\*.cs"
target="contentFiles/cs/netstandard2.0/Polyfill/StringInterpolation"/>
<file src="Trimming\*.cs"
target="contentFiles/cs/netstandard2.0/Polyfill/Trimming"/>
<file src="PlatformCompatibility\*.cs"
Expand Down
13 changes: 13 additions & 0 deletions src/Polyfill/Polyfill.targets
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,19 @@
<DefineConstants
Condition="$(HttpReferenced)">$(DefineConstants);HTTPREFERENCED</DefineConstants>
</PropertyGroup>
<PropertyGroup>
<DefineConstants Condition="$(MemoryReferenced)">$(DefineConstants);HAS_SPAN</DefineConstants>
<DefineConstants Condition="$(LowerFramework.StartsWith('net8'))">$(DefineConstants);HAS_SPAN</DefineConstants>
<DefineConstants Condition="$(LowerFramework.StartsWith('net7'))">$(DefineConstants);HAS_SPAN</DefineConstants>
<DefineConstants Condition="$(LowerFramework.StartsWith('net6'))">$(DefineConstants);HAS_SPAN</DefineConstants>
<DefineConstants Condition="$(LowerFramework.StartsWith('net5'))">$(DefineConstants);HAS_SPAN</DefineConstants>
<DefineConstants Condition="'$(LowerFramework)'=='netcoreapp3.1'">$(DefineConstants);HAS_SPAN</DefineConstants>
<DefineConstants Condition="'$(LowerFramework)'=='netcoreapp3.0'">$(DefineConstants);HAS_SPAN</DefineConstants>
<DefineConstants Condition="'$(LowerFramework)'=='netcoreapp2.2'">$(DefineConstants);HAS_SPAN</DefineConstants>
<DefineConstants Condition="'$(LowerFramework)'=='netcoreapp2.1'">$(DefineConstants);HAS_SPAN</DefineConstants>
<DefineConstants Condition="'$(LowerFramework)'=='netcoreapp2.0'">$(DefineConstants)</DefineConstants>
<DefineConstants Condition="$(LowerFramework.StartsWith('net4'))">$(DefineConstants)</DefineConstants>
</PropertyGroup>
</Target>
<ItemGroup>
<Compile Update="@(Compile)">
Expand Down
2 changes: 1 addition & 1 deletion src/Polyfill/PolyfillExtensions_String.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

static partial class PolyfillExtensions
{
#if (MEMORYREFERENCED && (NETFRAMEWORK || NETSTANDARD || NETCOREAPP)) || NET5_0
#if HAS_SPAN && !NET6_0_OR_GREATER

/// <summary>
/// Copies the contents of this string into the destination span.
Expand Down
95 changes: 88 additions & 7 deletions src/Polyfill/PolyfillExtensions_StringBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@

#pragma warning disable

#if MEMORYREFERENCED && (NETFRAMEWORK || NETSTANDARD2_0 || NETCOREAPP2_0)

using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using Link = System.ComponentModel.DescriptionAttribute;
using System.Threading;
using System.Threading.Tasks;
using Link = System.ComponentModel.DescriptionAttribute;

static partial class PolyfillExtensions
{
#if HAS_SPAN && (!NETSTANDARD2_1_OR_GREATER && !NETCOREAPP2_1_OR_GREATER)

/// <summary>
/// Copies the characters from a specified segment of this instance to a destination Char span.
/// </summary>
Expand Down Expand Up @@ -62,13 +63,13 @@ public static StringBuilder Append(this StringBuilder target, ReadOnlySpan<char>
#if AllowUnsafeBlocks
unsafe
{
fixed (char* valueChars = &MemoryMarshal.GetReference(value))
fixed (char* valueChars = value)
{
target.Append(valueChars, value.Length);
}
}
#else
target.Append(value.ToArray());
target.Append(value.ToString());
#endif
return target;
}
Expand Down Expand Up @@ -103,5 +104,85 @@ public static bool Equals(this StringBuilder target, ReadOnlySpan<char> span)

return true;
}
}
#endif

#endif
#if HAS_SPAN && !NET6_0_OR_GREATER
/// <summary>Appends the specified interpolated string to this instance.</summary>
/// <param name="handler">The interpolated string to append.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
[Link("https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.append#system-text-stringbuilder-append(system-text-stringbuilder-appendinterpolatedstringhandler@)")]
public static StringBuilder Append(
StringBuilder target,
[InterpolatedStringHandlerArgument(nameof(target))] ref AppendInterpolatedStringHandler handler) => target;

/// <summary>Appends the specified interpolated string to this instance.</summary>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="handler">The interpolated string to append.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
[Link("https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.append#system-text-stringbuilder-append(system-iformatprovider-system-text-stringbuilder-appendinterpolatedstringhandler@)")]
public static StringBuilder Append(
StringBuilder target,
IFormatProvider? provider,
[InterpolatedStringHandlerArgument(nameof(target), nameof(provider))] ref AppendInterpolatedStringHandler handler) => target;

/// <summary>Appends the specified interpolated string followed by the default line terminator to the end of the current StringBuilder object.</summary>
/// <param name="handler">The interpolated string to append.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
[Link("https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.appendline#system-text-stringbuilder-appendline(system-text-stringbuilder-appendinterpolatedstringhandler@)")]
public static StringBuilder AppendLine(
StringBuilder target,
[InterpolatedStringHandlerArgument(nameof(target))] ref AppendInterpolatedStringHandler handler) =>
target.AppendLine();

/// <summary>Appends the specified interpolated string followed by the default line terminator to the end of the current StringBuilder object.</summary>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="handler">The interpolated string to append.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
[Link("https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.appendline#system-text-stringbuilder-appendline(system-iformatprovider-system-text-stringbuilder-appendinterpolatedstringhandler@)")]
public static StringBuilder AppendLine(
StringBuilder target,
IFormatProvider? provider,
[InterpolatedStringHandlerArgument(nameof(target), nameof(provider))] ref AppendInterpolatedStringHandler handler) =>
target.AppendLine();
#elif NET6_0_OR_GREATER
/// <summary>Appends the specified interpolated string to this instance.</summary>
/// <param name="handler">The interpolated string to append.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
[Link("https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.append#system-text-stringbuilder-append(system-text-stringbuilder-appendinterpolatedstringhandler@)")]
public static StringBuilder Append(
StringBuilder target,
[InterpolatedStringHandlerArgument(nameof(target))] ref StringBuilder.AppendInterpolatedStringHandler handler) =>
target.Append(ref handler);

/// <summary>Appends the specified interpolated string to this instance.</summary>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="handler">The interpolated string to append.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
[Link("https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.append#system-text-stringbuilder-append(system-iformatprovider-system-text-stringbuilder-appendinterpolatedstringhandler@)")]
public static StringBuilder Append(
StringBuilder target,
IFormatProvider? provider,
[InterpolatedStringHandlerArgument(nameof(target), nameof(provider))] ref StringBuilder.AppendInterpolatedStringHandler handler) =>
target.Append(provider, ref handler);

/// <summary>Appends the specified interpolated string followed by the default line terminator to the end of the current StringBuilder object.</summary>
/// <param name="handler">The interpolated string to append.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
[Link("https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.appendline#system-text-stringbuilder-appendline(system-text-stringbuilder-appendinterpolatedstringhandler@)")]
public static StringBuilder AppendLine(
StringBuilder target,
[InterpolatedStringHandlerArgument(nameof(target))] ref StringBuilder.AppendInterpolatedStringHandler handler) =>
target.AppendLine(ref handler);

/// <summary>Appends the specified interpolated string followed by the default line terminator to the end of the current StringBuilder object.</summary>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="handler">The interpolated string to append.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
[Link("https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.appendline#system-text-stringbuilder-appendline(system-iformatprovider-system-text-stringbuilder-appendinterpolatedstringhandler@)")]
public static StringBuilder AppendLine(
StringBuilder target,
IFormatProvider? provider,
[InterpolatedStringHandlerArgument(nameof(target), nameof(provider))] ref StringBuilder.AppendInterpolatedStringHandler handler) =>
target.AppendLine(provider, ref handler);
#endif
}
Loading

0 comments on commit f1e0c6f

Please sign in to comment.