Skip to content

Commit

Permalink
Add PowerFx feature flag for User-defined types (#2667)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
adithyaselv authored Oct 3, 2024
1 parent 77ba570 commit 1507ae4
Show file tree
Hide file tree
Showing 9 changed files with 53 additions and 17 deletions.
8 changes: 8 additions & 0 deletions src/libraries/Microsoft.PowerFx.Core/Binding/Binder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5141,6 +5141,14 @@ private void PreVisitTypeArgAndProccesCallNode(CallNode node, TexlFunction func)
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]);

Expand Down
2 changes: 2 additions & 0 deletions src/libraries/Microsoft.PowerFx.Core/Localization/Strings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -848,5 +848,7 @@ internal static class TexlStrings
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");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ public sealed class Features
/// </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
Expand All @@ -105,7 +110,8 @@ public sealed class Features
PowerFxV1CompatibilityRules = true,
PrimaryOutputPropertyCoercionDeprecated = true,
AsTypeLegacyCheck = false,
JsonFunctionAcceptsLazyTypes = true
JsonFunctionAcceptsLazyTypes = true,
IsUserDefinedTypesEnabled = true
};

internal Features()
Expand All @@ -123,6 +129,7 @@ internal Features(Features other)
FirstLastNRequiresSecondArguments = other.FirstLastNRequiresSecondArguments;
PowerFxV1CompatibilityRules = other.PowerFxV1CompatibilityRules;
PrimaryOutputPropertyCoercionDeprecated = other.PrimaryOutputPropertyCoercionDeprecated;
IsUserDefinedTypesEnabled = other.IsUserDefinedTypesEnabled;
}
}
}
8 changes: 6 additions & 2 deletions src/strings/PowerFxResources.en-US.resx
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand All @@ -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>
Original file line number Diff line number Diff line change
Expand Up @@ -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})
Expand All @@ -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})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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})
Expand All @@ -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})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ public void Canvas_Float(ExpressionTestCase t)
var features = new Features()
{
TableSyntaxDoesntWrapRecords = true,
ConsistentOneColumnTableResult = true
ConsistentOneColumnTableResult = true,
IsUserDefinedTypesEnabled = true,
};

RunExpressionTestCase(t, features, numberIsFloat: true, Console);
Expand All @@ -60,6 +61,7 @@ public void Canvas_Float_PFxV1(ExpressionTestCase t)
TableSyntaxDoesntWrapRecords = true,
ConsistentOneColumnTableResult = true,
PowerFxV1CompatibilityRules = true,
IsUserDefinedTypesEnabled = true,
};

RunExpressionTestCase(t, features, numberIsFloat: true, Console);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ public class AsTypeIsTypeParseJSONTests
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);
}

Expand Down Expand Up @@ -148,6 +149,18 @@ public void TestCompileErrors(string expression, string type, bool testAllFuncti
}
}

[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()
{
Expand Down

0 comments on commit 1507ae4

Please sign in to comment.