Initial work on Color and Color_UO (#464)

* Initial work on Color and Color_UO

* Add ColorValue tests

* Add Color_UO tests

* Add empty string handling to ColorValue

* Add GUID impl

* Add GUID_UO

* Fix bug in GUID_UO

* Add TimeValue_UO

* Add Regex.Compiled option

* Remove ColorValue C#

* Update GUID print output
This commit is contained in:
bryancroteau-MSFT 2022-07-08 15:21:32 -07:00 коммит произвёл GitHub
Родитель 57e2e4bb9d
Коммит 6b4273f043
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
11 изменённых файлов: 222 добавлений и 22 удалений

Просмотреть файл

@ -79,6 +79,7 @@ namespace Microsoft.PowerFx.Core.Texl
public static readonly TexlFunction First = _library.Append(new FirstLastFunction(isFirst: true));
public static readonly TexlFunction FirstN = _library.Append(new FirstLastNFunction(isFirst: true));
public static readonly TexlFunction ForAll = _library.Append(new ForAllFunction());
public static readonly TexlFunction GUIDPure = _library.Append(new GUIDPureFunction());
public static readonly TexlFunction Hour = _library.Append(new HourFunction());
public static readonly TexlFunction If = _library.Append(new IfFunction());
public static readonly TexlFunction IfError = _library.Append(new IfErrorFunction());
@ -205,7 +206,10 @@ namespace Microsoft.PowerFx.Core.Texl
public static readonly TexlFunction Boolean_UO = _featureGateFunctions.Append(new BooleanFunction_UO());
public static readonly TexlFunction CountRows_UO = _featureGateFunctions.Append(new CountRowsFunction_UO());
public static readonly TexlFunction DateValue_UO = _featureGateFunctions.Append(new DateValueFunction_UO());
public static readonly TexlFunction TimeValue_UO = _featureGateFunctions.Append(new TimeValueFunction_UO());
public static readonly TexlFunction DateTimeValue_UO = _featureGateFunctions.Append(new DateTimeValueFunction_UO());
public static readonly TexlFunction GUID_UO = _featureGateFunctions.Append(new GUIDPureFunction_UO());
public static readonly TexlFunction ColorValue_UO = _featureGateFunctions.Append(new ColorValueFunction_UO());
public static readonly TexlFunction IsUTCToday = _featureGateFunctions.Append(new IsUTCTodayFunction());
public static readonly TexlFunction UTCNow = _featureGateFunctions.Append(new UTCNowFunction());

Просмотреть файл

@ -6,21 +6,39 @@ using Microsoft.PowerFx.Core.Functions;
using Microsoft.PowerFx.Core.Localization;
using Microsoft.PowerFx.Core.Types;
#pragma warning disable SA1402 // File may only contain a single type
#pragma warning disable SA1649 // File name should match first type name
namespace Microsoft.PowerFx.Core.Texl.Builtins
{
// ColorValue(colorstring:s)
// Returns the color value for the given color string
internal sealed class ColorValueFunction : BuiltinFunction
{
public const string ColorValueFunctionInvariantName = "ColorValue";
public override bool IsSelfContained => true;
public override bool SupportsParamCoercion => false;
public ColorValueFunction()
: base("ColorValue", TexlStrings.AboutColorValue, FunctionCategories.Color, DType.Color, 0, 1, 1, DType.String)
: base(ColorValueFunctionInvariantName, TexlStrings.AboutColorValue, FunctionCategories.Color, DType.Color, 0, 1, 1, DType.String)
{
}
public override IEnumerable<TexlStrings.StringGetter[]> GetSignatures()
{
yield return new[] { TexlStrings.ColorValueArg1 };
}
}
// ColorValue(colorstring:uo)
// ColorValue UntypedObject override
internal sealed class ColorValueFunction_UO : BuiltinFunction
{
public override bool IsSelfContained => true;
public override bool SupportsParamCoercion => false;
public ColorValueFunction_UO()
: base(ColorValueFunction.ColorValueFunctionInvariantName, TexlStrings.AboutColorValue, FunctionCategories.Color, DType.Color, 0, 1, 1, DType.UntypedObject)
{
}
@ -30,6 +48,3 @@ namespace Microsoft.PowerFx.Core.Texl.Builtins
}
}
}
#pragma warning restore SA1402 // File may only contain a single type
#pragma warning restore SA1649 // File name should match first type name

Просмотреть файл

@ -14,9 +14,6 @@ using Microsoft.PowerFx.Core.Types.Enums;
using Microsoft.PowerFx.Core.Utils;
using Microsoft.PowerFx.Syntax;
#pragma warning disable SA1402 // File may only contain a single type
#pragma warning disable SA1649 // File name should match first type name
namespace Microsoft.PowerFx.Core.Texl.Builtins
{
// Date()
@ -331,12 +328,14 @@ namespace Microsoft.PowerFx.Core.Texl.Builtins
// TimeValue(time_text:s, [languageCode:s]) : T
internal sealed class TimeValueFunction : DateTimeGenericFunction
{
public const string TimeValueFunctionInvariantName = "TimeValue";
public override bool HasPreciseErrors => true;
public override bool SupportsParamCoercion => true;
public TimeValueFunction()
: base("TimeValue", TexlStrings.AboutTimeValue, DType.Time)
: base(TimeValueFunctionInvariantName, TexlStrings.AboutTimeValue, DType.Time)
{
}
@ -713,6 +712,26 @@ namespace Microsoft.PowerFx.Core.Texl.Builtins
}
}
// TimeValue(time_text:uo) : T
internal sealed class TimeValueFunction_UO : BuiltinFunction
{
public override bool HasPreciseErrors => true;
public override bool SupportsParamCoercion => false;
public override bool IsSelfContained => true;
public TimeValueFunction_UO()
: base(TimeValueFunction.TimeValueFunctionInvariantName, TexlStrings.AboutTimeValue, FunctionCategories.DateTime, DType.Time, 0, 1, 1, DType.UntypedObject)
{
}
public override IEnumerable<TexlStrings.StringGetter[]> GetSignatures()
{
yield return new[] { TexlStrings.TimeValueArg1 };
}
}
// DateTimeValue(arg:O) : d
internal sealed class DateTimeValueFunction_UO : BuiltinFunction
{
@ -738,6 +757,3 @@ namespace Microsoft.PowerFx.Core.Texl.Builtins
}
}
}
#pragma warning restore SA1402 // File may only contain a single type
#pragma warning restore SA1649 // File name should match first type name

Просмотреть файл

@ -6,15 +6,14 @@ using Microsoft.PowerFx.Core.Functions;
using Microsoft.PowerFx.Core.Localization;
using Microsoft.PowerFx.Core.Types;
#pragma warning disable SA1402 // File may only contain a single type
#pragma warning disable SA1649 // File name should match first type name
// These have separate defintions as the one with a string is a pure function
namespace Microsoft.PowerFx.Core.Texl.Builtins
{
// GUID()
internal sealed class GUIDNoArgFunction : BuiltinFunction
{
public const string GUIDFunctionInvariantName = "GUID";
// Multiple invocations may produce different return values.
public override bool IsStateless => false;
@ -23,7 +22,7 @@ namespace Microsoft.PowerFx.Core.Texl.Builtins
public override bool SupportsParamCoercion => true;
public GUIDNoArgFunction()
: base("GUID", TexlStrings.AboutGUID, FunctionCategories.Text, DType.Guid, 0, 0, 0)
: base(GUIDFunctionInvariantName, TexlStrings.AboutGUID, FunctionCategories.Text, DType.Guid, 0, 0, 0)
{
}
@ -41,7 +40,25 @@ namespace Microsoft.PowerFx.Core.Texl.Builtins
public override bool SupportsParamCoercion => false;
public GUIDPureFunction()
: base("GUID", TexlStrings.AboutGUID, FunctionCategories.Text, DType.Guid, 0, 1, 1, DType.String)
: base(GUIDNoArgFunction.GUIDFunctionInvariantName, TexlStrings.AboutGUID, FunctionCategories.Text, DType.Guid, 0, 1, 1, DType.String)
{
}
public override IEnumerable<TexlStrings.StringGetter[]> GetSignatures()
{
yield return new[] { TexlStrings.GUIDArg };
}
}
// GUID(GuidString:uo)
internal sealed class GUIDPureFunction_UO : BuiltinFunction
{
public override bool IsSelfContained => true;
public override bool SupportsParamCoercion => false;
public GUIDPureFunction_UO()
: base(GUIDNoArgFunction.GUIDFunctionInvariantName, TexlStrings.AboutGUID, FunctionCategories.Text, DType.Guid, 0, 1, 1, DType.UntypedObject)
{
}
@ -51,6 +68,3 @@ namespace Microsoft.PowerFx.Core.Texl.Builtins
}
}
}
#pragma warning restore SA1402 // File may only contain a single type
#pragma warning restore SA1649 // File name should match first type name

Просмотреть файл

@ -108,6 +108,26 @@ namespace Microsoft.PowerFx.Functions
});
}
public static ErrorValue InvalidColorFormatError(IRContext irContext)
{
return new ErrorValue(irContext, new ExpressionError()
{
Message = "The value could not be interpreted as a Color",
Span = irContext.SourceContext,
Kind = ErrorKind.InvalidArgument
});
}
public static ErrorValue InvalidGuidFormatError(IRContext irContext)
{
return new ErrorValue(irContext, new ExpressionError()
{
Message = "The value could not be interpreted as a GUID",
Span = irContext.SourceContext,
Kind = ErrorKind.InvalidArgument
});
}
public static ErrorValue UnreachableCodeError(IRContext irContext)
{
return new ErrorValue(irContext, new ExpressionError()

Просмотреть файл

@ -545,6 +545,26 @@ namespace Microsoft.PowerFx.Functions
returnBehavior: ReturnBehavior.ReturnBlankIfAnyArgIsBlank,
targetFunction: ForAll)
},
{
BuiltinFunctionsCore.GUIDPure,
StandardErrorHandling<StringValue>(
expandArguments: NoArgExpansion,
replaceBlankValues: DoNotReplaceBlank,
checkRuntimeTypes: ExactValueTypeOrBlank<StringValue>,
checkRuntimeValues: DeferRuntimeValueChecking,
returnBehavior: ReturnBehavior.ReturnBlankIfAnyArgIsBlank,
targetFunction: Guid)
},
{
BuiltinFunctionsCore.GUID_UO,
StandardErrorHandling<UntypedObjectValue>(
expandArguments: NoArgExpansion,
replaceBlankValues: DoNotReplaceBlank,
checkRuntimeTypes: ExactValueTypeOrBlank<UntypedObjectValue>,
checkRuntimeValues: DeferRuntimeValueChecking,
returnBehavior: ReturnBehavior.ReturnBlankIfAnyArgIsBlank,
targetFunction: Guid_UO)
},
{
BuiltinFunctionsCore.IsBlank,
StandardErrorHandling<FormulaValue>(
@ -1175,6 +1195,16 @@ namespace Microsoft.PowerFx.Functions
returnBehavior: ReturnBehavior.ReturnBlankIfAnyArgIsBlank,
targetFunction: TimeParse)
},
{
BuiltinFunctionsCore.TimeValue_UO,
StandardErrorHandling<UntypedObjectValue>(
expandArguments: NoArgExpansion,
replaceBlankValues: DoNotReplaceBlank,
checkRuntimeTypes: ExactValueTypeOrBlank<UntypedObjectValue>,
checkRuntimeValues: DeferRuntimeValueChecking,
returnBehavior: ReturnBehavior.ReturnBlankIfAnyArgIsBlank,
targetFunction: TimeValue_UO)
},
{
BuiltinFunctionsCore.TimeZoneOffset,
StandardErrorHandling<FormulaValue>(

Просмотреть файл

@ -532,5 +532,20 @@ namespace Microsoft.PowerFx.Functions
return new StringValue(irContext, result);
}
public static FormulaValue Guid(IRContext irContext, StringValue[] args)
{
var text = args[0].Value;
try
{
var guid = new Guid(text);
return new GuidValue(irContext, guid);
}
catch
{
return CommonErrors.GenericInvalidArgument(irContext);
}
}
}
}

Просмотреть файл

@ -157,6 +157,24 @@ namespace Microsoft.PowerFx.Functions
return CommonErrors.RuntimeTypeMismatch(irContext);
}
public static FormulaValue TimeValue_UO(IRContext irContext, UntypedObjectValue[] args)
{
var impl = args[0].Impl;
if (impl.Type == FormulaType.String)
{
var s = impl.GetString();
if (TimeSpan.TryParseExact(s, @"hh\:mm\:ss\.FFF", CultureInfo.InvariantCulture, TimeSpanStyles.None, out TimeSpan res))
{
return new TimeValue(irContext, res);
}
return CommonErrors.InvalidDateTimeError(irContext);
}
return CommonErrors.RuntimeTypeMismatch(irContext);
}
public static FormulaValue DateTimeValue_UO(IRContext irContext, UntypedObjectValue[] args)
{
var impl = args[0].Impl;
@ -179,5 +197,18 @@ namespace Microsoft.PowerFx.Functions
return CommonErrors.RuntimeTypeMismatch(irContext);
}
public static FormulaValue Guid_UO(IRContext irContext, UntypedObjectValue[] args)
{
var impl = args[0].Impl;
if (impl.Type == FormulaType.String)
{
var str = new StringValue(IRContext.NotInSource(FormulaType.String), impl.GetString());
return Guid(irContext, new StringValue[] { str });
}
return CommonErrors.RuntimeTypeMismatch(irContext);
}
}
}

Просмотреть файл

@ -0,0 +1,33 @@
>> GUID("5cc45615-f759-4a53-b225-d3a2497f60ad")
GUID("5cc45615-f759-4a53-b225-d3a2497f60ad")
// No dashes
>> GUID("5cc45615f7594a53b225d3a2497f60ad")
GUID("5cc45615-f759-4a53-b225-d3a2497f60ad")
// Upper case
>> GUID("C203B79B-B985-42F0-B523-C10EB64387C6")
GUID("c203b79b-b985-42f0-b523-c10eb64387c6")
// Correct format, invalid chars
>> GUID("5zz45615-f759-4a53-b225-d3a2497f60ad")
#Error(Kind=InvalidArgument)
// Dashes in wrong place
>> GUID("5cc45615-f75-94a5-3b225d3a24-97f60ad")
#Error(Kind=InvalidArgument)
>> GUID(Text(1/0))
#Error(Kind=Div0)
>> GUID(Blank())
Blank()
>> GUID("")
#Error(Kind=InvalidArgument)
>> GUID("shortstring")
#Error(Kind=InvalidArgument)
>> GUID("thisisastringthatismuchlongerthanaguidshouldbeitisquitealongstringandwillfinderrorswithlongstringsinthisfunction")
#Error(Kind=InvalidArgument)

Просмотреть файл

@ -157,3 +157,21 @@ Blank()
>> DateTimeValue(ParseJSON("""abcdef"""))
#Error(Kind=InvalidArgument)
>> Text(TimeValue(ParseJSON("""08:03:05.000""")))
"8:03 AM"
>> TimeValue(ParseJSON("""08:93:05.000"""))
#Error(Kind=InvalidArgument)
>> TimeValue(ParseJSON("null"))
Blank()
>> TimeValue(ParseJSON("""abcdef"""))
#Error(Kind=InvalidArgument)
>> GUID(ParseJSON("""5cc45615-f759-4a53-b225-d3a2497f60ad"""))
GUID("5cc45615-f759-4a53-b225-d3a2497f60ad")
>> GUID(ParseJSON("null"))
Blank()

Просмотреть файл

@ -378,6 +378,10 @@ namespace Microsoft.PowerFx.Core.Tests
{
sb.Append($"{opt.Type.OptionSetName}.{opt.Option}");
}
else if (result is GuidValue gv)
{
sb.Append($"GUID(\"{gv.Value}\")");
}
else if (result is ErrorValue)
{
sb.Append(result);