Add PowerFx feature flag for User-defined types (#2667)

Add PowerFx feature flag for User-defined types to show compile error
when a function that uses UDT type argument is used when the feature is
turned off. This PR also also fixes an error message string

I would also like to cleanup the Parser flag `AllowTypeLiteral` and use
only feature flag, but that needs bit more refactoring and will do in a
follow up PR
This commit is contained in:
Adithya Selvaprithiviraj 2024-10-02 17:42:36 -07:00 коммит произвёл GitHub
Родитель 77ba57001b
Коммит 1507ae41b5
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
9 изменённых файлов: 53 добавлений и 17 удалений

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

@ -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]);

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

@ -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");
}
}

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

@ -91,6 +91,11 @@ namespace Microsoft.PowerFx
/// </summary>
internal bool IsLookUpReductionDelegationEnabled { get; set; }
/// <summary>
/// Enables User-defined types functionality.
/// </summary>
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;
}
}
}

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

@ -4765,7 +4765,7 @@
<comment>Error Message shown to user when a value other name or type literal is passed into AsType, IsType and ParseJSON functions.</comment>
</data>
<data name="ErrUnsupportedTypeInTypeArgument" xml:space="preserve">
<value>Unsupported untyped/JSON conversion type '{0}' in argument.</value>
<value>Unsupported type '{0}' in type argument.</value>
<comment>Error Message shown to user when a unsupported type is passed in type argument of AsType, IsType and ParseJSON functions.</comment>
</data>
<data name="ErrReachedMaxJsonDepth" xml:space="preserve">
@ -4775,5 +4775,9 @@
<data name="ErrReachedMaxJsonLength" xml:space="preserve">
<value>Maximum length reached in JSON function.</value>
<comment>Error message returned by the {Locked=JSON} function when the result generated by this function would be too long.</comment>
</data>
</data>
<data name="ErrUserDefinedTypesDisabled" xml:space="preserve">
<value>The 'User-defined types' experimental feature is not enabled.</value>
<comment>Error message returned when user uses User-defined types with the User-defined types feature flag turned off.</comment>
</data>
</root>

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

@ -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})

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

@ -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})

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

@ -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})

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

@ -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);

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

@ -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()
{