Skip to content

Commit

Permalink
Support "Old" string concat behavior
Browse files Browse the repository at this point in the history
Prior to v5.1, NCalc would treat + as string concatenation if the first argument was a string. Later versions changed this logic and while they did add options to control it, no combination of those options restored the old behavior.

The Tech Software fork exists to allow callers to opt-in to the old behavior.
  • Loading branch information
mattwTS committed Oct 10, 2024
1 parent 67d11ea commit 9cdb71c
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 13 deletions.
17 changes: 8 additions & 9 deletions .github/workflows/publish-nuget.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ jobs:
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Configure NuGet
run: dotnet nuget add source https://nuget.pkg.github.com/tech-software/index.json --name github --username tech-software --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text
- name: Restore dependencies
run: dotnet restore
- name: Build
Expand All @@ -29,15 +31,12 @@ jobs:
run: dotnet test -c Release --no-build --verbosity normal
- name: Pack unsigned
run: dotnet pack -c Release --no-build -p:PublicRelease=true
- name: Pack signed
run: dotnet pack -c SignedRelease -p:PublicRelease=true
- name: Publish packages
run: |
dotnet nuget push src/NCalc.Core/bin/Release/NCalc.Core*.nupkg --api-key "${{ secrets.NUGET_NCALC_PLUGINS_API_TOKEN }}" --source https://api.nuget.org/v3/index.json --skip-duplicate
dotnet nuget push src/NCalc.Sync/bin/Release/NCalcSync*.nupkg --api-key "${{ secrets.NUGET_NCALC_SYNC_API_TOKEN }}" --source https://api.nuget.org/v3/index.json --skip-duplicate
dotnet nuget push src/NCalc.Sync/bin/SignedRelease/NCalcSync*.nupkg --api-key "${{ secrets.NUGET_NCALC_SYNC_API_TOKEN }}" --source https://api.nuget.org/v3/index.json --skip-duplicate
dotnet nuget push src/NCalc.Async/bin/Release/NCalcAsync*.nupkg --api-key "${{ secrets.NUGET_NCALC_PLUGINS_API_TOKEN }}" --source https://api.nuget.org/v3/index.json --skip-duplicate
dotnet nuget push src/NCalc.DependencyInjection/bin/Release/NCalc.DependencyInjection*.nupkg --api-key "${{ secrets.NUGET_NCALC_PLUGINS_API_TOKEN }}" --source https://api.nuget.org/v3/index.json --skip-duplicate
dotnet nuget push src/Plugins/NCalc.MemoryCache/bin/Release/NCalc.MemoryCache*.nupkg --api-key "${{ secrets.NUGET_NCALC_PLUGINS_API_TOKEN }}" --source https://api.nuget.org/v3/index.json --skip-duplicate
dotnet nuget push src/Plugins/NCalc.Antlr/bin/Release/NCalc.Antlr*.nupkg --api-key "${{ secrets.NUGET_NCALC_PLUGINS_API_TOKEN }}" --source https://api.nuget.org/v3/index.json --skip-duplicate
dotnet nuget push src/NCalc.Core/bin/Release/TSNCalc.Core*.nupkg --api-key "${{ secrets.GITHUB_TOKEN }}" --source github --skip-duplicate
dotnet nuget push src/NCalc.Sync/bin/Release/TSNCalcSync*.nupkg --api-key "${{ secrets.GITHUB_TOKEN }}" --source github --skip-duplicate
# dotnet nuget push src/NCalc.Async/bin/Release/NCalcAsync*.nupkg --api-key "${{ secrets.GITHUB_TOKEN }}" --source github --skip-duplicate
# dotnet nuget push src/NCalc.DependencyInjection/bin/Release/NCalc.DependencyInjection*.nupkg --api-key "${{ secrets.GITHUB_TOKEN }}" --source github --skip-duplicate
# dotnet nuget push src/Plugins/NCalc.MemoryCache/bin/Release/NCalc.MemoryCache*.nupkg --api-key "${{ secrets.GITHUB_TOKEN }}" --source github --skip-duplicate
# dotnet nuget push src/Plugins/NCalc.Antlr/bin/Release/NCalc.Antlr*.nupkg --api-key "${{ secrets.GITHUB_TOKEN }}" --source github --skip-duplicate
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PackageIcon>NCalc.png</PackageIcon>
<Authors>Sebastien Ros and contributors</Authors>
<Copyright>Sebastien Ros and contributors</Copyright>
<Company>https://github.com/ncalc</Company>
<Company>https://github.com/tech-software</Company>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
Expand Down
11 changes: 10 additions & 1 deletion src/NCalc.Core/ExpressionOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,14 @@ public enum ExpressionOptions
/// <summary>
/// Return the value instead of throwing an exception when the expression is null or empty.
/// </summary>
AllowNullOrEmptyExpressions = 1 << 14
AllowNullOrEmptyExpressions = 1 << 14,

/// <summary>
/// Use the pre-NCalc 5.1 behavior for string concatenation.
/// </summary>
/// <remarks>
/// <p>If the left value is a string, the result of + will be string concatenation.
/// Otherwise both parameters will be converted to numeric if needed and possible.</p>
/// </remarks>
UseOldStringConcatBehavior = 1 << 31,
}
8 changes: 8 additions & 0 deletions src/NCalc.Core/Helpers/EvaluationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,15 @@ public static class EvaluationHelper
public static object? Plus(object? leftValue, object? rightValue, ExpressionContextBase context)
{
if (context.Options.HasFlag(ExpressionOptions.StringConcat))
{
return string.Concat(leftValue, rightValue);
}

if (context.Options.HasFlag(ExpressionOptions.UseOldStringConcatBehavior) &&
leftValue is string)
{
return string.Concat(leftValue, rightValue);
}

if (context.Options.HasFlag(ExpressionOptions.NoStringTypeCoercion) &&
(leftValue is string || rightValue is string))
Expand Down
2 changes: 1 addition & 1 deletion src/NCalc.Core/NCalc.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFrameworks>net462;netstandard2.0;net6.0;net8.0</TargetFrameworks>
<LangVersion>12</LangVersion>
<Nullable>enable</Nullable>
<PackageId>NCalc.Core</PackageId>
<PackageId>TSNCalc.Core</PackageId>
<AssemblyName>NCalc.Core</AssemblyName>
<Description>Assembly with the core logic of NCalc.</Description>
<SignAssembly>true</SignAssembly>
Expand Down
2 changes: 1 addition & 1 deletion src/NCalc.Sync/NCalc.Sync.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<!-- Unsigned Assembly Configuration -->
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' Or '$(Configuration)' == 'Release' ">
<AssemblyName>NCalc.Sync</AssemblyName>
<PackageId>NCalcSync</PackageId>
<PackageId>TSNCalcSync</PackageId>
<Description>NCalc is a fast and lightweight expression evaluator library for .NET, designed for flexibility and high performance. It supports a wide range of mathematical and logical operations. NCalc can parse any expression and evaluate the result, including static or dynamic parameters and custom functions. This package contains the unsigned assembly 'NCalc'. For the stronly signed assembly version of 'NCalc', see the NCalcSync.signed package.</Description>
</PropertyGroup>

Expand Down
31 changes: 31 additions & 0 deletions test/NCalc.Tests/UseOldStringConcatBehaviorTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
namespace NCalc.Tests;

[Trait("Category", "UseOldStringConcatBehavior")]
public class UseOldStringConcatBehaviorTests
{
[Theory]
[InlineData("'to' + 'to'", "toto")]
[InlineData("'one' + 2", "one2")]
[InlineData("'one' + 2.1", "one2.1")]
[InlineData("'1' + '2'", "12")]
[InlineData("'1.1' + '2'", "1.12")]
[InlineData("'1' + '2.2'", "12.2")]
[InlineData("1 + 2", 3)]
[InlineData("1.5 + 2.5", 4.0)]
[InlineData("1 + '2'", 3.0)]
[InlineData("1.5 + '2.5'", 4.0)]
[InlineData("'10' + 'mA - ' + (10 + 20) + 'mA'", "10mA - 30mA")]
public void ShouldUseStringConcatenationIfFirstValueIsAString(string expression, object expected)
{
Assert.Equal(expected, new Expression(expression, ExpressionOptions.UseOldStringConcatBehavior).Evaluate());
}

[Theory]
[InlineData("2 + 'one'")]
[InlineData("2.1 + 'one'")]
public void ShouldThrowIfFirstValueIsNumericAndSecondIsNot(string expression)
{
Assert.Throws<FormatException>(()
=> new Expression(expression, ExpressionOptions.UseOldStringConcatBehavior).Evaluate());
}
}

0 comments on commit 9cdb71c

Please sign in to comment.