diff --git a/src/libraries/Microsoft.PowerFx.Core/Public/Engine.cs b/src/libraries/Microsoft.PowerFx.Core/Public/Engine.cs
index 480bab8594..01aba402d2 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Public/Engine.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Public/Engine.cs
@@ -84,9 +84,9 @@ public Engine(PowerFxConfig powerFxConfig)
public ReadOnlySymbolTable SupportedFunctions { get; protected internal set; } = _allBuiltinCoreFunctions;
///
- /// Builtin Types supported by this engine.
+ /// Builtin Types supported by this engine for UDFs and UDTs.
///
- public ReadOnlySymbolTable PrimitiveTypes { get; protected internal set; } = ReadOnlySymbolTable.PrimitiveTypesTableInstance;
+ public ReadOnlySymbolTable PrimitiveTypes { get; protected internal set; }
// By default, we pull the core functions.
// These can be overridden.
diff --git a/src/libraries/Microsoft.PowerFx.Core/Public/Types/BooleanType.cs b/src/libraries/Microsoft.PowerFx.Core/Public/Types/BooleanType.cs
index 31f64aa13c..b5465dcd89 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Public/Types/BooleanType.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Public/Types/BooleanType.cs
@@ -3,11 +3,14 @@
using System.Text;
using Microsoft.PowerFx.Core.Types;
+using Microsoft.PowerFx.Core.Utils;
namespace Microsoft.PowerFx.Types
{
public class BooleanType : FormulaType
{
+ public override DName Name => new DName("Boolean");
+
internal BooleanType()
: base(DType.Boolean)
{
diff --git a/src/libraries/Microsoft.PowerFx.Core/Public/Types/ColorType.cs b/src/libraries/Microsoft.PowerFx.Core/Public/Types/ColorType.cs
index cc4b8a687c..ba4d9c6a16 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Public/Types/ColorType.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Public/Types/ColorType.cs
@@ -4,11 +4,14 @@
using System;
using System.Text;
using Microsoft.PowerFx.Core.Types;
+using Microsoft.PowerFx.Core.Utils;
namespace Microsoft.PowerFx.Types
{
public class ColorType : FormulaType
{
+ public override DName Name => new DName("Color");
+
internal ColorType()
: base(DType.Color)
{
diff --git a/src/libraries/Microsoft.PowerFx.Core/Public/Types/DateTimeNoTimeZoneType.cs b/src/libraries/Microsoft.PowerFx.Core/Public/Types/DateTimeNoTimeZoneType.cs
index 0902c6e77c..bc03b346a6 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Public/Types/DateTimeNoTimeZoneType.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Public/Types/DateTimeNoTimeZoneType.cs
@@ -3,12 +3,15 @@
using System.Diagnostics;
using Microsoft.PowerFx.Core.Types;
+using Microsoft.PowerFx.Core.Utils;
namespace Microsoft.PowerFx.Types
{
[DebuggerDisplay("{_type}:tzi")]
public class DateTimeNoTimeZoneType : FormulaType
{
+ public override DName Name => new DName("DateTimeTZInd");
+
internal DateTimeNoTimeZoneType()
: base(DType.DateTimeNoTimeZone)
{
diff --git a/src/libraries/Microsoft.PowerFx.Core/Public/Types/DateTimeType.cs b/src/libraries/Microsoft.PowerFx.Core/Public/Types/DateTimeType.cs
index 89837f98f2..f9ad82d55f 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Public/Types/DateTimeType.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Public/Types/DateTimeType.cs
@@ -10,6 +10,8 @@ namespace Microsoft.PowerFx.Types
{
public class DateTimeType : FormulaType
{
+ public override DName Name => new DName("DateTime");
+
internal DateTimeType()
: base(DType.DateTime)
{
diff --git a/src/libraries/Microsoft.PowerFx.Core/Public/Types/DateType.cs b/src/libraries/Microsoft.PowerFx.Core/Public/Types/DateType.cs
index 0ed02e46e1..5507bbf16f 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Public/Types/DateType.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Public/Types/DateType.cs
@@ -9,6 +9,8 @@ namespace Microsoft.PowerFx.Types
{
public class DateType : FormulaType
{
+ public override DName Name => new DName("Date");
+
internal DateType()
: base(DType.Date)
{
diff --git a/src/libraries/Microsoft.PowerFx.Core/Public/Types/DecimalType.cs b/src/libraries/Microsoft.PowerFx.Core/Public/Types/DecimalType.cs
index dc3e9ea217..18b83e115f 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Public/Types/DecimalType.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Public/Types/DecimalType.cs
@@ -2,12 +2,15 @@
// Licensed under the MIT license.
using System.Text;
-using Microsoft.PowerFx.Core.Types;
+using Microsoft.PowerFx.Core.Types;
+using Microsoft.PowerFx.Core.Utils;
namespace Microsoft.PowerFx.Types
{
public class DecimalType : FormulaType
- {
+ {
+ public override DName Name => new DName("Decimal");
+
internal DecimalType()
: base(DType.Decimal)
{
diff --git a/src/libraries/Microsoft.PowerFx.Core/Public/Types/FormulaType.cs b/src/libraries/Microsoft.PowerFx.Core/Public/Types/FormulaType.cs
index 9ecc268047..e7f25a3797 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Public/Types/FormulaType.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Public/Types/FormulaType.cs
@@ -23,7 +23,9 @@ public abstract class FormulaType
#pragma warning disable SA1300 // Element should begin with upper-case letter
// Uses init to allow setting from derived constructors. Otherwise, is immutable.
internal DType _type { get; private protected init; }
-#pragma warning restore SA1300 // Element should begin with upper-case letter
+#pragma warning restore SA1300 // Element should begin with upper-case letter
+
+ public virtual DName Name { get; }
public static FormulaType Blank { get; } = new BlankType();
@@ -76,20 +78,20 @@ internal FormulaType(DType type)
internal static readonly IReadOnlyDictionary PrimitiveTypes = ImmutableDictionary.CreateRange(new Dictionary()
{
- { new DName("Boolean"), Boolean },
- { new DName("Color"), Color },
- { new DName("Date"), Date },
- { new DName("Time"), Time },
- { new DName("DateTime"), DateTime },
- { new DName("DateTimeTZInd"), DateTimeNoTimeZone },
- { new DName("GUID"), Guid },
- { new DName("Number"), Number },
- { new DName("Decimal"), Decimal },
- { new DName("Text"), String },
- { new DName("Hyperlink"), Hyperlink },
- { new DName("None"), Blank },
- { new DName("Dynamic"), UntypedObject },
- { new DName("Void"), Void },
+ { Boolean.Name, Boolean },
+ { Color.Name, Color },
+ { Date.Name, Date },
+ { Time.Name, Time },
+ { DateTime.Name, DateTime },
+ { DateTimeNoTimeZone.Name, DateTimeNoTimeZone },
+ { Guid.Name, Guid },
+ { Number.Name, Number },
+ { Decimal.Name, Decimal },
+ { String.Name, String },
+ { Hyperlink.Name, Hyperlink },
+ { Blank.Name, Blank },
+ { UntypedObject.Name, UntypedObject },
+ { Void.Name, Void },
});
///
diff --git a/src/libraries/Microsoft.PowerFx.Core/Public/Types/GuidType.cs b/src/libraries/Microsoft.PowerFx.Core/Public/Types/GuidType.cs
index ecfb52a3cb..9f627f0bbf 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Public/Types/GuidType.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Public/Types/GuidType.cs
@@ -10,6 +10,8 @@ namespace Microsoft.PowerFx.Types
{
public class GuidType : FormulaType
{
+ public override DName Name => new DName("GUID");
+
internal GuidType()
: base(DType.Guid)
{
diff --git a/src/libraries/Microsoft.PowerFx.Core/Public/Types/HyperlinkType.cs b/src/libraries/Microsoft.PowerFx.Core/Public/Types/HyperlinkType.cs
index 40ea2cee8b..7887d60104 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Public/Types/HyperlinkType.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Public/Types/HyperlinkType.cs
@@ -3,11 +3,14 @@
using System;
using Microsoft.PowerFx.Core.Types;
+using Microsoft.PowerFx.Core.Utils;
namespace Microsoft.PowerFx.Types
{
public class HyperlinkType : FormulaType
{
+ public override DName Name => new DName("Hyperlink");
+
internal HyperlinkType()
: base(DType.Hyperlink)
{
diff --git a/src/libraries/Microsoft.PowerFx.Core/Public/Types/NumberType.cs b/src/libraries/Microsoft.PowerFx.Core/Public/Types/NumberType.cs
index 9f1f435706..22fe14d3b9 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Public/Types/NumberType.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Public/Types/NumberType.cs
@@ -3,11 +3,14 @@
using System.Text;
using Microsoft.PowerFx.Core.Types;
+using Microsoft.PowerFx.Core.Utils;
namespace Microsoft.PowerFx.Types
{
public class NumberType : FormulaType
{
+ public override DName Name => new DName("Number");
+
internal NumberType()
: base(DType.Number)
{
diff --git a/src/libraries/Microsoft.PowerFx.Core/Public/Types/StringType.cs b/src/libraries/Microsoft.PowerFx.Core/Public/Types/StringType.cs
index 66d38e070e..31fc0c47f4 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Public/Types/StringType.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Public/Types/StringType.cs
@@ -9,6 +9,8 @@ namespace Microsoft.PowerFx.Types
{
public class StringType : FormulaType
{
+ public override DName Name => new DName("Text");
+
public StringType()
: base(DType.String)
{
diff --git a/src/libraries/Microsoft.PowerFx.Core/Public/Types/TimeType.cs b/src/libraries/Microsoft.PowerFx.Core/Public/Types/TimeType.cs
index 1761084269..f513f23307 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Public/Types/TimeType.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Public/Types/TimeType.cs
@@ -4,11 +4,14 @@
using System;
using System.Text;
using Microsoft.PowerFx.Core.Types;
+using Microsoft.PowerFx.Core.Utils;
namespace Microsoft.PowerFx.Types
{
public class TimeType : FormulaType
{
+ public override DName Name => new DName("Time");
+
internal TimeType()
: base(DType.Time)
{
diff --git a/src/libraries/Microsoft.PowerFx.Core/Public/Types/UntypedObjectType.cs b/src/libraries/Microsoft.PowerFx.Core/Public/Types/UntypedObjectType.cs
index 39a55ad342..086192b7c1 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Public/Types/UntypedObjectType.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Public/Types/UntypedObjectType.cs
@@ -5,11 +5,14 @@
using System.Collections.Generic;
using System.Text;
using Microsoft.PowerFx.Core.Types;
+using Microsoft.PowerFx.Core.Utils;
namespace Microsoft.PowerFx.Types
{
public class UntypedObjectType : FormulaType
{
+ public override DName Name => new DName("Dynamic");
+
public UntypedObjectType()
: base(DType.UntypedObject)
{
diff --git a/src/libraries/Microsoft.PowerFx.Core/Public/Types/Void.cs b/src/libraries/Microsoft.PowerFx.Core/Public/Types/Void.cs
index 0c36c932ac..3b6451da6e 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Public/Types/Void.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Public/Types/Void.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license.
using Microsoft.PowerFx.Core.Types;
+using Microsoft.PowerFx.Core.Utils;
using Microsoft.PowerFx.Types;
namespace Microsoft.PowerFx.Types
@@ -11,6 +12,8 @@ namespace Microsoft.PowerFx.Types
///
public sealed class Void : FormulaType
{
+ public override DName Name => new DName("Void");
+
internal Void()
: base(DType.Void)
{
diff --git a/src/libraries/Microsoft.PowerFx.Core/Syntax/UserDefinitions.cs b/src/libraries/Microsoft.PowerFx.Core/Syntax/UserDefinitions.cs
index 47edc98322..aa2e6a4e21 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Syntax/UserDefinitions.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Syntax/UserDefinitions.cs
@@ -35,7 +35,7 @@ internal sealed class UserDefinitions
///
/// Restricted return type.
///
- public static readonly ISet RestrictedTypes = ImmutableHashSet.Create(DType.DateTimeNoTimeZone, DType.ObjNull, DType.Decimal);
+ public static readonly ISet RestrictedTypes = ImmutableHashSet.Create(DType.ObjNull);
///
/// REstricted parameter type.
diff --git a/src/libraries/Microsoft.PowerFx.Core/Texl/Builtins/UntypedOrJSONConversionFunction.cs b/src/libraries/Microsoft.PowerFx.Core/Texl/Builtins/UntypedOrJSONConversionFunction.cs
index 44381bb084..cfd7243948 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Texl/Builtins/UntypedOrJSONConversionFunction.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Texl/Builtins/UntypedOrJSONConversionFunction.cs
@@ -37,6 +37,10 @@ public override bool HasSuggestionsForParam(int argIndex)
return argIndex == 1;
}
+ // This list is intersected with Engine.PrimitiveTypes, with outliers generating errors before this list is checked.
+ // In other words, just because a type is listed here, does not mean it is supported unless it is also in Engine.PrimitiveTypes.
+ // Notably this list excludes ObjNull and Void, which make no sense to use in JSON or UDFs (except for UDF return type for Void).
+ // It also excludes Color, as we have not implemented the coversion of "Red" and other color names. We could convert # hex colors but this has not been done.
internal static readonly ISet SupportedJSONTypes = new HashSet { DType.Boolean, DType.Number, DType.Decimal, DType.Date, DType.DateTime, DType.DateTimeNoTimeZone, DType.Time, DType.String, DType.Guid, DType.Hyperlink, DType.UntypedObject };
public UntypedOrJSONConversionFunction(string name, TexlStrings.StringGetter description, DType returnType, int arityMax, params DType[] paramTypes)
diff --git a/src/libraries/Microsoft.PowerFx.Interpreter/RecalcEngine.cs b/src/libraries/Microsoft.PowerFx.Interpreter/RecalcEngine.cs
index f85f9ad6e4..2200481bc1 100644
--- a/src/libraries/Microsoft.PowerFx.Interpreter/RecalcEngine.cs
+++ b/src/libraries/Microsoft.PowerFx.Interpreter/RecalcEngine.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Collections.Immutable;
using System.Globalization;
using System.Linq;
using System.Text;
@@ -43,6 +44,23 @@ public RecalcEngine()
{
}
+ internal static readonly ReadOnlySymbolTable _recalcPrimitiveTypes =
+ SymbolTable.NewDefaultTypes(ImmutableDictionary.CreateRange(new Dictionary()
+ {
+ { FormulaType.Boolean.Name, FormulaType.Boolean },
+ { FormulaType.Color.Name, FormulaType.Color },
+ { FormulaType.Date.Name, FormulaType.Date },
+ { FormulaType.Time.Name, FormulaType.Time },
+ { FormulaType.DateTime.Name, FormulaType.DateTime },
+ { FormulaType.Guid.Name, FormulaType.Guid },
+ { FormulaType.Number.Name, FormulaType.Number },
+ { FormulaType.Decimal.Name, FormulaType.Decimal },
+ { FormulaType.String.Name, FormulaType.String }, // Text
+ { FormulaType.Hyperlink.Name, FormulaType.Hyperlink },
+ { FormulaType.UntypedObject.Name, FormulaType.UntypedObject }, // Dynamic
+ { FormulaType.Void.Name, FormulaType.Void },
+ }));
+
public RecalcEngine(PowerFxConfig powerFxConfig)
: base(powerFxConfig)
{
@@ -52,6 +70,8 @@ public RecalcEngine(PowerFxConfig powerFxConfig)
base.EngineSymbols = _symbolTable;
+ base.PrimitiveTypes = _recalcPrimitiveTypes;
+
// Add Builtin functions that aren't yet in the shared library.
SupportedFunctions = _interpreterSupportedFunctions;
}
diff --git a/src/tests/Microsoft.PowerFx.Core.Tests.Shared/ExpressionTestCases/AsType_UO.txt b/src/tests/Microsoft.PowerFx.Core.Tests.Shared/ExpressionTestCases/AsType_UO.txt
index 8a45880cfb..a62b7ecf04 100644
--- a/src/tests/Microsoft.PowerFx.Core.Tests.Shared/ExpressionTestCases/AsType_UO.txt
+++ b/src/tests/Microsoft.PowerFx.Core.Tests.Shared/ExpressionTestCases/AsType_UO.txt
@@ -48,10 +48,10 @@ true
false
>> AsType(ParseJSON("""1900-12-31T00:00:00.000Z"""), DateTimeTZInd)
-DateTime(1900,12,31,0,0,0,0)
+Errors: Error 50-63: Name isn't valid. 'DateTimeTZInd' isn't recognized.|Error 0-64: Invalid argument 'DateTimeTZInd'. Expected valid type name or inline type expression.
>> AsType(ParseJSON("""1900-12-31T00:00:00.000-08:00"""), DateTimeTZInd)
-DateTime(1900,12,31,8,0,0,0)
+Errors: Error 55-68: Name isn't valid. 'DateTimeTZInd' isn't recognized.|Error 0-69: Invalid argument 'DateTimeTZInd'. Expected valid type name or inline type expression.
>> Value(AsType(ParseJSON("42"), Dynamic))
42
@@ -119,10 +119,10 @@ Errors: Error 26-30: Unsupported type 'Void' in type argument.
Errors: Error 0-59: Invalid number of arguments: received 3, expected 2.
>> AsType(ParseJSON("true"), None)
-Errors: Error 26-30: Unsupported type 'Blank' in type argument.
+Errors: Error 26-30: Name isn't valid. 'None' isn't recognized.|Error 0-31: Invalid argument 'None'. Expected valid type name or inline type expression.
>> AsType(ParseJSON("null"), None)
-Errors: Error 26-30: Unsupported type 'Blank' in type argument.
+Errors: Error 26-30: Name isn't valid. 'None' isn't recognized.|Error 0-31: Invalid argument 'None'. Expected valid type name or inline type expression.
>> AsType(ParseJSON("{}"), Type({a: Text, b: [Color]}))
Errors: Error 28-29: Unsupported type 'Color' in type argument.
diff --git a/src/tests/Microsoft.PowerFx.Core.Tests.Shared/ExpressionTestCases/IsType_UO.txt b/src/tests/Microsoft.PowerFx.Core.Tests.Shared/ExpressionTestCases/IsType_UO.txt
index 744f29c50b..197badeee3 100644
--- a/src/tests/Microsoft.PowerFx.Core.Tests.Shared/ExpressionTestCases/IsType_UO.txt
+++ b/src/tests/Microsoft.PowerFx.Core.Tests.Shared/ExpressionTestCases/IsType_UO.txt
@@ -45,7 +45,7 @@ true
true
>> IsType(ParseJSON("""1900-12-31T00:00:00.000Z"""), DateTimeTZInd)
-true
+Errors: Error 50-63: Name isn't valid. 'DateTimeTZInd' isn't recognized.|Error 0-64: Invalid argument 'DateTimeTZInd'. Expected valid type name or inline type expression.
>> IsType(ParseJSON("""true"""), Boolean)
false
@@ -111,7 +111,7 @@ Errors: Error 26-30: Unsupported type 'Void' in type argument.
Errors: Error 0-59: Invalid number of arguments: received 3, expected 2.
>> IsType(ParseJSON("true"), None)
-Errors: Error 26-30: Unsupported type 'Blank' in type argument.
+Errors: Error 26-30: Name isn't valid. 'None' isn't recognized.|Error 0-31: Invalid argument 'None'. Expected valid type name or inline type expression.
>> IsType(ParseJSON("{}"), Type({a: Text, b: [Color]}))
Errors: Error 28-29: Unsupported type 'Color' in type argument.
diff --git a/src/tests/Microsoft.PowerFx.Core.Tests.Shared/ExpressionTestCases/TypedParseJSON.txt b/src/tests/Microsoft.PowerFx.Core.Tests.Shared/ExpressionTestCases/TypedParseJSON.txt
index 9ae205a278..d71d9e5399 100644
--- a/src/tests/Microsoft.PowerFx.Core.Tests.Shared/ExpressionTestCases/TypedParseJSON.txt
+++ b/src/tests/Microsoft.PowerFx.Core.Tests.Shared/ExpressionTestCases/TypedParseJSON.txt
@@ -48,10 +48,10 @@ true
false
>> ParseJSON("""1900-12-31T00:00:00.000Z""", DateTimeTZInd)
-DateTime(1900,12,31,0,0,0,0)
+Errors: Error 42-55: Name isn't valid. 'DateTimeTZInd' isn't recognized.|Error 0-56: Invalid argument 'DateTimeTZInd'. Expected valid type name or inline type expression.
>> ParseJSON("""1900-12-31T00:00:00.000-08:00""", DateTimeTZInd)
-DateTime(1900,12,31,8,0,0,0)
+Errors: Error 47-60: Name isn't valid. 'DateTimeTZInd' isn't recognized.|Error 0-61: Invalid argument 'DateTimeTZInd'. Expected valid type name or inline type expression.
>> Value(ParseJSON("42", Dynamic))
42
@@ -128,10 +128,10 @@ Errors: Error 18-22: Unsupported type 'Void' in type argument.
Errors: Error 0-51: Invalid number of arguments: received 3, expected 2.
>> ParseJSON("true", None)
-Errors: Error 18-22: Unsupported type 'Blank' in type argument.
+Errors: Error 18-22: Name isn't valid. 'None' isn't recognized.|Error 0-23: Invalid argument 'None'. Expected valid type name or inline type expression.
>> ParseJSON("null", None)
-Errors: Error 18-22: Unsupported type 'Blank' in type argument.
+Errors: Error 18-22: Name isn't valid. 'None' isn't recognized.|Error 0-23: Invalid argument 'None'. Expected valid type name or inline type expression.
>> ParseJSON("{}", Type({a: Text, b: [Color]}))
Errors: Error 20-21: Unsupported type 'Color' in type argument.
diff --git a/src/tests/Microsoft.PowerFx.Core.Tests.Shared/UserDefinedFunctionTests.cs b/src/tests/Microsoft.PowerFx.Core.Tests.Shared/UserDefinedFunctionTests.cs
index d30a9a14a5..b5764f2fae 100644
--- a/src/tests/Microsoft.PowerFx.Core.Tests.Shared/UserDefinedFunctionTests.cs
+++ b/src/tests/Microsoft.PowerFx.Core.Tests.Shared/UserDefinedFunctionTests.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Collections.Immutable;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
@@ -13,6 +14,7 @@
using Microsoft.PowerFx.Core.IR;
using Microsoft.PowerFx.Core.Syntax;
using Microsoft.PowerFx.Core.Texl;
+using Microsoft.PowerFx.Core.Utils;
using Microsoft.PowerFx.Syntax;
using Microsoft.PowerFx.Types;
using Xunit;
@@ -435,7 +437,15 @@ public void BasicEngine()
var extra = new SymbolTable();
extra.AddVariable("K1", FormulaType.Number);
- var engine = new Engine();
+ var engine = new Engine()
+ {
+ PrimitiveTypes =
+ SymbolTable.NewDefaultTypes(ImmutableDictionary.CreateRange(new Dictionary()
+ {
+ { new DName("Number"), FormulaType.Number },
+ }))
+ };
+
engine.AddUserDefinedFunction("Foo1(x: Number): Number = Abs(K1);", symbolTable: extra);
var check = engine.Check("Foo1(3)");
@@ -503,10 +513,8 @@ public void TestUDF(string formula, int nfCount, int udfCount, int validUdfCount
[Theory]
[InlineData("Foo(x: Number): None = Abs(x);")]
[InlineData("Foo(x: None): Number = Abs(x);")]
- [InlineData("Foo(x: Decimal): Number = Abs(x);")]
- [InlineData("Foo(x: Number): Decimal = Abs(x);")]
- [InlineData("Foo(x: DateTimeTZInd): Decimal = Abs(x);")]
- [InlineData("Foo(x: Number): DateTimeTZInd = Abs(x);")]
+ [InlineData("Foo(x: Void): Number = Abs(x);")]
+ [InlineData("Foo(x: Number): Void = Abs(x);")]
public void TestUDFsWithRestrictedTypes(string script)
{
var parserOptions = new ParserOptions()
@@ -518,7 +526,7 @@ public void TestUDFsWithRestrictedTypes(string script)
var udfs = UserDefinedFunction.CreateFunctions(parseResult.UDFs.Where(udf => udf.IsParseValid), _primitiveTypes, out var errors);
errors.AddRange(parseResult.Errors ?? Enumerable.Empty());
- Assert.Contains(errors, x => x.MessageKey == "ErrUDF_InvalidReturnType" || x.MessageKey == "ErrUDF_InvalidParamType");
+ Assert.Contains(errors, x => x.MessageKey == "ErrUDF_NonImperativeVoidType" || x.MessageKey == "ErrUDF_UnknownType" || x.MessageKey == "ErrUDF_InvalidReturnType" || x.MessageKey == "ErrUDF_InvalidParamType");
}
[Theory]
diff --git a/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/IntellisenseTests/UDFIntellisenseTests.cs b/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/IntellisenseTests/UDFIntellisenseTests.cs
index f1befc35df..f8981dd9e0 100644
--- a/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/IntellisenseTests/UDFIntellisenseTests.cs
+++ b/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/IntellisenseTests/UDFIntellisenseTests.cs
@@ -3,8 +3,10 @@
using System;
using System.Collections.Generic;
+using System.Collections.Immutable;
using System.Linq;
using System.Text;
+using Microsoft.PowerFx.Core.Utils;
using Microsoft.PowerFx.Intellisense;
using Microsoft.PowerFx.Types;
using Xunit;
@@ -17,15 +19,34 @@ public class UDFIntellisenseTests
[InlineData("AddNumbers(x: Number, y: Number): Number = x + y; |", "")]
[InlineData("AddNumbers(x: Number, y: Number): Number = x + |", "")]
[InlineData("AddNumbers(x: Number, y: Number): Number = x + Su|", "ErrorKind.InsufficientMemory,ErrorKind.NotSupported,StartOfWeek.Sunday,Sum,Substitute,TraceOptions.IgnoreUnsupportedTypes")]
- [InlineData("AddNumbers(x: Number, y: Number): |", "Boolean,Color,Date,DateTime,Dynamic,GUID,Hyperlink,Number,Text,Time,Void")]
- [InlineData("AddNumbers(x: Number, y: |", "Boolean,Color,Date,DateTime,Dynamic,GUID,Hyperlink,Number,Text,Time")]
+ [InlineData("AddNumbers(x: Number, y: Number): |", "Boolean,Color,Date,DateTime,Decimal,Dynamic,GUID,Hyperlink,Number,Text,Time,Void")]
+ [InlineData("AddNumbers(x: Number, y: |", "Boolean,Color,Date,DateTime,Decimal,Dynamic,GUID,Hyperlink,Number,Text,Time")]
// Suggest UDF names when calling one UDF from another
[InlineData("AddNumbers(x: Number, y: Number): Number = x + y; AddNumbers2(x: Number, y: Text): Number = AddNum|", "AddNumbers")]
public void UDFSuggestionTest(string expression, string expected)
{
var config = new PowerFxConfig();
- var engine = new Engine(config);
+ var engine = new Engine(config)
+ {
+ PrimitiveTypes = SymbolTable.NewDefaultTypes(ImmutableDictionary.CreateRange(new Dictionary()
+ {
+ { FormulaType.Boolean.Name, FormulaType.Boolean },
+ { FormulaType.Color.Name, FormulaType.Color },
+ { FormulaType.Date.Name, FormulaType.Date },
+ { FormulaType.Time.Name, FormulaType.Time },
+ { FormulaType.DateTime.Name, FormulaType.DateTime },
+ { FormulaType.DateTimeNoTimeZone.Name, FormulaType.DateTimeNoTimeZone },
+ { FormulaType.Guid.Name, FormulaType.Guid },
+ { FormulaType.Number.Name, FormulaType.Number },
+ { FormulaType.Decimal.Name, FormulaType.Decimal },
+ { FormulaType.String.Name, FormulaType.String },
+ { FormulaType.Hyperlink.Name, FormulaType.Hyperlink },
+ { FormulaType.Blank.Name, FormulaType.Blank },
+ { FormulaType.UntypedObject.Name, FormulaType.UntypedObject },
+ { FormulaType.Void.Name, FormulaType.Void },
+ }))
+ };
var scope = engine.CreateUDFEditorScope();
// engine.AddUserDefinedFunction(expression);
diff --git a/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/RecalcEngineTests.cs b/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/RecalcEngineTests.cs
index 96f4c88e2e..1f48eeb1db 100644
--- a/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/RecalcEngineTests.cs
+++ b/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/RecalcEngineTests.cs
@@ -1973,20 +1973,20 @@ protected override bool TryGetField(FormulaType fieldType, string fieldName, out
Patients := Type([Patient]);
Dummy():Number = CountRows([]);",
"Dummy()",
- true,
+ false,
true,
0.0)]
// Aggregate types with restricted types are not allowed in UDF
[InlineData(
- @"Patient := Type({DOB: DateTimeTZInd, Weight: Decimal, Dummy: None});
+ @"Patient := Type({DOB: DateTimeTZInd, Weight: Void, Dummy: None});
Patients := Type([Patient]);
getAnomaly(p: Patients): Patients = Filter(p, Weight < 0);",
"",
false)]
[InlineData(
- @"Patient := Type({Name: Text, Details: {h: Number, w:Decimal}});
+ @"Patient := Type({Name: Text, Details: {h: Number, w:Void}});
getPatient(): Patient = {Name:""Alice"", Details: {h: 1, w: 2}};",
"",
false)]
diff --git a/src/tests/Microsoft.PowerFx.Json.Tests.Shared/AsTypeIsTypeParseJSONTests.cs b/src/tests/Microsoft.PowerFx.Json.Tests.Shared/AsTypeIsTypeParseJSONTests.cs
index a679870987..6254560944 100644
--- a/src/tests/Microsoft.PowerFx.Json.Tests.Shared/AsTypeIsTypeParseJSONTests.cs
+++ b/src/tests/Microsoft.PowerFx.Json.Tests.Shared/AsTypeIsTypeParseJSONTests.cs
@@ -51,7 +51,6 @@ public void PrimitivesTest()
CheckIsTypeAsTypeParseJSON(engine, "\"1234.56789\"", "Decimal", 1234.56789m);
CheckIsTypeAsTypeParseJSON(engine, "\"42\"", "T", 42D);
CheckIsTypeAsTypeParseJSON(engine, "\"\"\"Power Fx\"\"\"", "Type(Text)", "Power Fx");
- CheckIsTypeAsTypeParseJSON(engine, "\"\"\"2000-01-01T00:00:01.100Z\"\"\"", "DateTimeTZInd", new DateTime(2000, 1, 1, 0, 0, 1, 100));
CheckIsTypeAsTypeParseJSON(engine, "\"\"\"11:59:59\"\"\"", "Time", new TimeSpan(11, 59, 59));
// Negative tests - Coercions not allowed
@@ -62,7 +61,7 @@ public void PrimitivesTest()
CheckIsTypeAsTypeParseJSON(engine, "\"true\"", "Number", false, false);
// Negative tests - types not supported in FromJSON converter
- CheckIsTypeAsTypeParseJSONCompileErrors(engine, "\"42\"", "None", TexlStrings.ErrUnsupportedTypeInTypeArgument.Key);
+ CheckIsTypeAsTypeParseJSONCompileErrors(engine, "\"42\"", "None", TexlStrings.ErrInvalidArgumentExpectedType.Key);
CheckIsTypeAsTypeParseJSONCompileErrors(engine, "\"\"\"RED\"\"\"", "Color", TexlStrings.ErrUnsupportedTypeInTypeArgument.Key);
CheckIsTypeAsTypeParseJSON(engine, "\"\"\"abcd-efgh-1234-ijkl\"\"\"", "GUID", string.Empty, false);
CheckIsTypeAsTypeParseJSON(engine, "\"\"\"foo/bar/uri\"\"\"", "Hyperlink", string.Empty, false);