Skip to content
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
6 changes: 4 additions & 2 deletions src/Simpleflow/CodeGenerator/SimpleflowCodeVisitor.Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,18 @@ private Expression GetNumberExpression(string value, Type targetType)
targetType == typeof(decimal) ||
targetType == typeof(double) ||
targetType == typeof(float) ||
targetType == typeof(object) ||
targetType == typeof(byte))
{
return Expression.Constant(Convert.ChangeType(value, targetType), targetType);
}
throw new Exceptions.ValueTypeMismatchException(value, targetType.Name);
}

private Expression GetBoolExpression(string value)
private Expression GetBoolExpression(string value, Type targetType)
{
return Expression.Constant(Convert.ToBoolean(value), typeof(bool));
return Expression.Constant(Convert.ToBoolean(value), targetType == null || targetType == typeof(bool)
? typeof(bool) : targetType );
}

private string GetUnquotedEscapeText(string @string)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,21 @@ public override Expression VisitNotExpression([NotNull] SimpleflowParser.NotExpr
private Expression InOperatorExpression(Expression left, Expression right)
{
if (right.Type.GenericTypeArguments.Length == 0
|| right.Type != typeof(List<>).MakeGenericType(right.Type.GenericTypeArguments[0]))
|| right.Type.IsAssignableFrom( typeof(IList<>).MakeGenericType(right.Type.GenericTypeArguments[0])))
{
throw new Exceptions.SimpleflowException(Resources.Message.InOperatorOnList);
}


// Try perform automatic conversion TODO Handle nulls
if (right.Type.GenericTypeArguments[0] == typeof(string))
{
left = ToStringExpression(left);
}
else if (right.Type.GenericTypeArguments[0] != left.Type)
{
left = Expression.Convert(left, right.Type.GenericTypeArguments[0]);
}

return Expression.Call(
right,
right.Type.GetMethod("Contains", right.Type.GenericTypeArguments),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,9 @@ private void CheckInvalidParameters(ParameterInfo[] actualMethodParameters, Simp
private Expression VisitObjectIdentiferAsPerTargetType(SimpleflowParser.ObjectIdentiferExpressionContext objectIdentifier, Type targetType)
{
var objectIdentieferText = objectIdentifier.GetText();

if (objectIdentieferText.Contains(".")

if ( objectIdentieferText.Contains(".") // accessing property
|| objectIdentifier.objectIdentifier()?.identifierIndex()[0]?.index() != null
|| Variables.Any(v => string.Equals(v.Name, objectIdentieferText, StringComparison.OrdinalIgnoreCase)))
{
return Visit(objectIdentifier); // regular object identifier used from variables
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ public override Expression VisitBoolLeteral([NotNull] SimpleflowParser.BoolLeter

var value = context.GetText();

if (targetType == null || targetType == typeof(bool))
if (targetType == null || targetType == typeof(bool) || targetType == typeof(object))
{
return GetBoolExpression(value);
return GetBoolExpression(value, targetType);
}

throw new ValueTypeMismatchException(value);
Expand All @@ -62,11 +62,7 @@ public override Expression VisitStringLiteral([NotNull] SimpleflowParser.StringL

var value = GetUnquotedEscapeText(context.String().GetText());

if (targetType == null || targetType == typeof(string))
{
return Expression.Constant(value);
}
else if (targetType != null && targetType.IsEnum) // Handle enum
if (targetType != null && targetType.IsEnum) // Handle Enum
{
if (!TryParseEnum(targetType, value, out object result))
{
Expand All @@ -75,6 +71,11 @@ public override Expression VisitStringLiteral([NotNull] SimpleflowParser.StringL
return Expression.Constant(result, targetType);
}

if (targetType == null || targetType == typeof(string) || targetType == typeof(object))
{
return Expression.Constant(value);
}

throw new ValueTypeMismatchException(value);
}

Expand Down
3 changes: 3 additions & 0 deletions src/Simpleflow/FunctionRegister.BuiltIn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ public static FunctionRegister Default
.Add("Length", (Func<string, int>)StringFunctions.Length)
.Add("Match", (Func<string, string, bool>)StringFunctions.Match)
.Add("Concat", (Func<string, string, string, string, string, string>)StringFunctions.Concat)

.Add("Str", (Func<object, string>)DataTypeConversionFunctions.Str)

;
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/Simpleflow/Functions/DataTypeConversionFunctions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright (c) navtech.io. All rights reserved.
// See License in the project root for license information.

namespace Simpleflow.Functions
{
internal static class DataTypeConversionFunctions
{
public static string Str(object value) => value?.ToString() ?? string.Empty;
}
}
4 changes: 2 additions & 2 deletions src/Simpleflow/Simpleflow.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
<PropertyGroup>
<TargetFrameworks>net48;netcoreapp3.1;net6.0;</TargetFrameworks>
<PackageIcon>PackageIcon.png</PackageIcon>
<VersionPrefix>1.0.11</VersionPrefix>
<VersionSuffix></VersionSuffix>
<VersionPrefix>1.0.12</VersionPrefix>
<VersionSuffix>beta1</VersionSuffix>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>

Expand Down
196 changes: 196 additions & 0 deletions test/Simpleflow.Tests/Functions/DataTypeConversionFunctions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
// Copyright (c) navtech.io. All rights reserved.
// See License in the project root for license information.

using System;
using System.Collections.Generic;
using System.Text;
using Xunit;

namespace Simpleflow.Tests.Functions
{
public class StringFunctionsTest
{
[Fact]
public void CheckContains()
{
// Arrange
var script =
@"

let hasValue = $Contains(input: arg.Text, value: ""here"" )
let hasValue2 = $Contains(input: arg.Text, value: ""no"" )

output hasValue
output hasValue2
";

// Act
FlowOutput output = SimpleflowEngine.Run(script, new { Text = "its here" });

// Assert
Assert.True((bool)output.Output["hasValue"]);
Assert.False((bool)output.Output["hasValue2"]);
}

[Fact]
public void CheckStartsWithEndsWith()
{
// Arrange
var script =
@"

let hasValue = $StartsWith(input: arg.Text, value: ""its"" )
let hasValue2 = $EndsWith(input: arg.Text, value: ""here"" )

output hasValue
output hasValue2
";

// Act
FlowOutput output = SimpleflowEngine.Run(script, new { Text = "its here" });

// Assert
Assert.True((bool)output.Output["hasValue"]);
Assert.True((bool)output.Output["hasValue2"]);
}

[Fact]
public void CheckTrim()
{
// Arrange
var script =
@"

let trim = $Trim(input: arg.Text, value: "" @"" )

output trim
";

// Act
FlowOutput output = SimpleflowEngine.Run(script, new { Text = " its here@ " });

// Assert
Assert.Equal(expected: "its here", actual: output.Output["trim"]);
}

[Fact]
public void CheckIndexOf()
{
// Arrange
var script =
@"

let index = $IndexOf(input: arg.Text, value: ""here"" )

output index
";

// Act
FlowOutput output = SimpleflowEngine.Run(script, new { Text = " its here@ " });

// Assert
Assert.Equal(expected: 5, actual: output.Output["index"]);
}

[Fact]
public void CheckRegexMatch()
{
// Arrange
var script =
@"

let matched = $match(input: arg.Text, pattern: ""[0-9]*"" )

output matched
";

// Act
FlowOutput output = SimpleflowEngine.Run(script, new { Text = " its here 995 " });

// Assert
Assert.True((bool)output.Output["matched"]);
}

[Fact]
public void CheckSubstring()
{
// Arrange
var script =
@"

let text = $Substring(input: arg.Text, startIndex: 4 )
let text2 = $Substring(input: arg.Text, startIndex: 4, length: 2 )

output text
output text2
";

// Act
FlowOutput output = SimpleflowEngine.Run(script, new { Text = "its here" });

// Assert
Assert.Equal(actual: output.Output["text"], expected: "here");
Assert.Equal(actual: output.Output["text2"], expected: "he");

}

[Fact]
public void CheckStringLength()
{
// Arrange
var script =
@"

let len = $Length(input: arg.Text)

output len
";

// Act
FlowOutput output = SimpleflowEngine.Run(script, new { Text = "its here" });

// Assert
Assert.Equal(actual: output.Output["len"], expected: 8);
}

[Fact]
public void CheckStringConcat()
{
// Arrange
var script =
@"

let val = $Concat(value1: arg.Text, value2: "" abc"")

output val
";

// Act
FlowOutput output = SimpleflowEngine.Run(script, new { Text = "its here" });

// Assert
Assert.Equal(actual: output.Output["val"], expected: "its here abc");
}

[Fact]
public void CheckSubStringAndIndexOf()
{
// Arrange
var script =
@"

let text = $Substring(input: arg.Text,
startIndex: $IndexOf(input: arg.Text, value: '@') + 1
)
output text
";

// Act
FlowOutput output = SimpleflowEngine.Run(script, new { Text = " its here@com" });

// Assert
Assert.Equal(expected: "com", actual: output.Output["text"]);
}

}
}
Loading