diff --git a/src/libraries/Microsoft.PowerFx.Core/Binding/Binder.cs b/src/libraries/Microsoft.PowerFx.Core/Binding/Binder.cs index 12a973260..55d39c122 100644 --- a/src/libraries/Microsoft.PowerFx.Core/Binding/Binder.cs +++ b/src/libraries/Microsoft.PowerFx.Core/Binding/Binder.cs @@ -5141,6 +5141,14 @@ namespace Microsoft.PowerFx.Core.Binding return; } + if (!_features.IsUserDefinedTypesEnabled) + { + _txb.ErrorContainer.Error(node, TexlStrings.ErrUserDefinedTypesDisabled); + _txb.SetInfo(node, new CallInfo(func, node)); + _txb.SetType(node, DType.Error); + return; + } + Contracts.Assert(argCount > 1); Contracts.AssertValue(args[1]); diff --git a/src/libraries/Microsoft.PowerFx.Core/Localization/Strings.cs b/src/libraries/Microsoft.PowerFx.Core/Localization/Strings.cs index 63ce19862..cfd16f081 100644 --- a/src/libraries/Microsoft.PowerFx.Core/Localization/Strings.cs +++ b/src/libraries/Microsoft.PowerFx.Core/Localization/Strings.cs @@ -848,5 +848,7 @@ namespace Microsoft.PowerFx.Core.Localization public static ErrorResourceKey ErrUnsupportedTypeInTypeArgument = new ErrorResourceKey("ErrUnsupportedTypeInTypeArgument"); public static ErrorResourceKey ErrReachedMaxJsonDepth = new ErrorResourceKey("ErrReachedMaxJsonDepth"); public static ErrorResourceKey ErrReachedMaxJsonLength = new ErrorResourceKey("ErrReachedMaxJsonLength"); + + public static ErrorResourceKey ErrUserDefinedTypesDisabled = new ErrorResourceKey("ErrUserDefinedTypesDisabled"); } } diff --git a/src/libraries/Microsoft.PowerFx.Core/Public/Config/Features.cs b/src/libraries/Microsoft.PowerFx.Core/Public/Config/Features.cs index 2e4c83cd3..4c4ec848f 100644 --- a/src/libraries/Microsoft.PowerFx.Core/Public/Config/Features.cs +++ b/src/libraries/Microsoft.PowerFx.Core/Public/Config/Features.cs @@ -91,6 +91,11 @@ namespace Microsoft.PowerFx /// internal bool IsLookUpReductionDelegationEnabled { get; set; } + /// + /// Enables User-defined types functionality. + /// + internal bool IsUserDefinedTypesEnabled { get; set; } = false; + internal static Features None => new Features(); public static Features PowerFxV1 => new Features @@ -105,7 +110,8 @@ namespace Microsoft.PowerFx PowerFxV1CompatibilityRules = true, PrimaryOutputPropertyCoercionDeprecated = true, AsTypeLegacyCheck = false, - JsonFunctionAcceptsLazyTypes = true + JsonFunctionAcceptsLazyTypes = true, + IsUserDefinedTypesEnabled = true }; internal Features() @@ -123,6 +129,7 @@ namespace Microsoft.PowerFx FirstLastNRequiresSecondArguments = other.FirstLastNRequiresSecondArguments; PowerFxV1CompatibilityRules = other.PowerFxV1CompatibilityRules; PrimaryOutputPropertyCoercionDeprecated = other.PrimaryOutputPropertyCoercionDeprecated; + IsUserDefinedTypesEnabled = other.IsUserDefinedTypesEnabled; } } } diff --git a/src/strings/PowerFxResources.en-US.resx b/src/strings/PowerFxResources.en-US.resx index 06c0828c9..2d8747429 100644 --- a/src/strings/PowerFxResources.en-US.resx +++ b/src/strings/PowerFxResources.en-US.resx @@ -4765,7 +4765,7 @@ Error Message shown to user when a value other name or type literal is passed into AsType, IsType and ParseJSON functions. - Unsupported untyped/JSON conversion type '{0}' in argument. + Unsupported type '{0}' in type argument. Error Message shown to user when a unsupported type is passed in type argument of AsType, IsType and ParseJSON functions. @@ -4775,5 +4775,9 @@ Maximum length reached in JSON function. Error message returned by the {Locked=JSON} function when the result generated by this function would be too long. - + + + The 'User-defined types' experimental feature is not enabled. + Error message returned when user uses User-defined types with the User-defined types feature flag turned off. + \ No newline at end of file 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 54f38fe36..b294c06ac 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 @@ -130,7 +130,7 @@ Errors: Error 26-33: Name isn't valid. 'UnKnown' isn't recognized.|Error 0-34: I Error({Kind:ErrorKind.InvalidJSON}) >> AsType(ParseJSON("true"), Void) -Errors: Error 26-30: Unsupported untyped/JSON conversion type 'Void' in argument. +Errors: Error 26-30: Unsupported type 'Void' in type argument. >> AsType(ParseJSON("{""a"": 5, ""b"":true}"), Type({a: Number})) Error({Kind:ErrorKind.InvalidArgument}) @@ -139,13 +139,13 @@ Error({Kind:ErrorKind.InvalidArgument}) Errors: Error 0-59: Invalid number of arguments: received 3, expected 2. >> AsType(ParseJSON("true"), None) -Errors: Error 26-30: Unsupported untyped/JSON conversion type 'ObjNull' in argument. +Errors: Error 26-30: Unsupported type 'ObjNull' in type argument. >> AsType(ParseJSON("null"), None) -Errors: Error 26-30: Unsupported untyped/JSON conversion type 'ObjNull' in argument. +Errors: Error 26-30: Unsupported type 'ObjNull' in type argument. >> AsType(ParseJSON("{}"), Type({a: Text, b: [Color]})) -Errors: Error 28-29: Unsupported untyped/JSON conversion type 'Color' in argument. +Errors: Error 28-29: Unsupported type 'Color' in type argument. >> AsType(If(1/0 > 1, ParseJSON("42")), Number) Error({Kind:ErrorKind.Div0}) 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 1cb3b7049..f50e69da5 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 @@ -107,16 +107,16 @@ Errors: Error 26-33: Name isn't valid. 'UnKnown' isn't recognized.|Error 0-34: I Error({Kind:ErrorKind.InvalidJSON}) >> IsType(ParseJSON("true"), Void) -Errors: Error 26-30: Unsupported untyped/JSON conversion type 'Void' in argument. +Errors: Error 26-30: Unsupported type 'Void' in type argument. >> IsType(ParseJSON("{""a"": 5}"), Type({a: Number}), "Hello") Errors: Error 0-59: Invalid number of arguments: received 3, expected 2. >> IsType(ParseJSON("true"), None) -Errors: Error 26-30: Unsupported untyped/JSON conversion type 'ObjNull' in argument. +Errors: Error 26-30: Unsupported type 'ObjNull' in type argument. >> IsType(ParseJSON("{}"), Type({a: Text, b: [Color]})) -Errors: Error 28-29: Unsupported untyped/JSON conversion type 'Color' in argument. +Errors: Error 28-29: Unsupported type 'Color' in type argument. >> IsType(If(1/0 > 1, ParseJSON("42")), Number) Error({Kind:ErrorKind.Div0}) 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 1ebd178a7..abca5ad9c 100644 --- a/src/tests/Microsoft.PowerFx.Core.Tests.Shared/ExpressionTestCases/TypedParseJSON.txt +++ b/src/tests/Microsoft.PowerFx.Core.Tests.Shared/ExpressionTestCases/TypedParseJSON.txt @@ -121,7 +121,7 @@ Error({Kind:ErrorKind.InvalidArgument}) Errors: Error 15-16: Invalid argument '1'. Expected valid type name or type literal. >> ParseJSON("""RED""", Color) -Errors: Error 21-26: Unsupported untyped/JSON conversion type 'Color' in argument. +Errors: Error 21-26: Unsupported type 'Color' in type argument. >> ParseJSON("5", Type(5)) Errors: Error 20-21: Type literal declaration is invalid. The expression '5' cannot be used in a type definition.|Error 19-20: Type literal declaration is invalid. The expression 'Type(5)' cannot be used in a type definition. @@ -133,7 +133,7 @@ Errors: Error 18-25: Name isn't valid. 'UnKnown' isn't recognized.|Error 0-26: I Error({Kind:ErrorKind.InvalidJSON}) >> ParseJSON("true", Void) -Errors: Error 18-22: Unsupported untyped/JSON conversion type 'Void' in argument. +Errors: Error 18-22: Unsupported type 'Void' in type argument. >> ParseJSON("{""a"": 5, ""b"":true}", Type({a: Number})) Error({Kind:ErrorKind.InvalidArgument}) @@ -142,13 +142,13 @@ Error({Kind:ErrorKind.InvalidArgument}) Errors: Error 0-51: Invalid number of arguments: received 3, expected 2. >> ParseJSON("true", None) -Errors: Error 18-22: Unsupported untyped/JSON conversion type 'ObjNull' in argument. +Errors: Error 18-22: Unsupported type 'ObjNull' in type argument. >> ParseJSON("null", None) -Errors: Error 18-22: Unsupported untyped/JSON conversion type 'ObjNull' in argument. +Errors: Error 18-22: Unsupported type 'ObjNull' in type argument. >> ParseJSON("{}", Type({a: Text, b: [Color]})) -Errors: Error 20-21: Unsupported untyped/JSON conversion type 'Color' in argument. +Errors: Error 20-21: Unsupported type 'Color' in type argument. >> ParseJSON(If(1/0 > 1, "42"), Number) Error({Kind:ErrorKind.Div0}) diff --git a/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/FileExpressionEvaluationTests.cs b/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/FileExpressionEvaluationTests.cs index 524433dff..ed8850dbe 100644 --- a/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/FileExpressionEvaluationTests.cs +++ b/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/FileExpressionEvaluationTests.cs @@ -43,7 +43,8 @@ namespace Microsoft.PowerFx.Interpreter.Tests var features = new Features() { TableSyntaxDoesntWrapRecords = true, - ConsistentOneColumnTableResult = true + ConsistentOneColumnTableResult = true, + IsUserDefinedTypesEnabled = true, }; RunExpressionTestCase(t, features, numberIsFloat: true, Console); @@ -60,6 +61,7 @@ namespace Microsoft.PowerFx.Interpreter.Tests TableSyntaxDoesntWrapRecords = true, ConsistentOneColumnTableResult = true, PowerFxV1CompatibilityRules = true, + IsUserDefinedTypesEnabled = true, }; RunExpressionTestCase(t, features, numberIsFloat: true, Console); diff --git a/src/tests/Microsoft.PowerFx.Json.Tests.Shared/AsTypeIsTypeParseJSONTests.cs b/src/tests/Microsoft.PowerFx.Json.Tests.Shared/AsTypeIsTypeParseJSONTests.cs index c031431f4..57a56ccdd 100644 --- a/src/tests/Microsoft.PowerFx.Json.Tests.Shared/AsTypeIsTypeParseJSONTests.cs +++ b/src/tests/Microsoft.PowerFx.Json.Tests.Shared/AsTypeIsTypeParseJSONTests.cs @@ -26,10 +26,11 @@ namespace Microsoft.PowerFx.Json.Tests AllowParseAsTypeLiteral = true, }; - private RecalcEngine SetupEngine() + private RecalcEngine SetupEngine(bool udtFeaturedEnabled = true) { var config = new PowerFxConfig(); config.EnableJsonFunctions(); + config.Features.IsUserDefinedTypesEnabled = udtFeaturedEnabled; return new RecalcEngine(config); } @@ -148,6 +149,18 @@ namespace Microsoft.PowerFx.Json.Tests } } + [Theory] + [InlineData("AsType(ParseJSON(\"123\"), Number)")] + [InlineData("IsType(ParseJSON(\"123\"), Type(Number))")] + [InlineData("ParseJSON(\"\"\"Hello\"\"\", Type(Text))")] + public void TestCompileErrorsWithUDTFeatureDisabled(string expression) + { + var engine = SetupEngine(udtFeaturedEnabled: false); + var result = engine.Check(expression); + Assert.False(result.IsSuccess); + Assert.Contains(result.Errors, e => e.MessageKey == "ErrUserDefinedTypesDisabled"); + } + [Fact] public void TestFunctionsWithTypeArgs() {