From 42a16ef5e3e2ad7bf6f3eb3fdc38e3f0de556a5e Mon Sep 17 00:00:00 2001 From: anderson-joyle Date: Mon, 30 Dec 2024 09:17:45 -0600 Subject: [PATCH] Checkpoint. PA build was working before these changes. --- .../Microsoft.PowerFx.Core/Texl/Remove.cs | 191 +++++++----------- .../MutationScripts/Remove.txt | 3 + 2 files changed, 73 insertions(+), 121 deletions(-) diff --git a/src/libraries/Microsoft.PowerFx.Core/Texl/Remove.cs b/src/libraries/Microsoft.PowerFx.Core/Texl/Remove.cs index 44448845de..eeb666db20 100644 --- a/src/libraries/Microsoft.PowerFx.Core/Texl/Remove.cs +++ b/src/libraries/Microsoft.PowerFx.Core/Texl/Remove.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; +using System.Numerics; using Microsoft.PowerFx.Core.App.ErrorContainers; using Microsoft.PowerFx.Core.Binding; using Microsoft.PowerFx.Core.Entities; @@ -19,8 +20,7 @@ namespace Microsoft.PowerFx.Core.Texl.Builtins { - // Remove(collection:*[], item1:![], item2:![], ..., ["All"]) - internal class RemoveFunction : BuiltinFunction, ISuggestionAwareFunction + internal abstract class RemoveBaseFunction : BuiltinFunction { public override bool ManipulatesCollections => true; @@ -30,24 +30,14 @@ internal class RemoveFunction : BuiltinFunction, ISuggestionAwareFunction public override bool IsSelfContained => false; - public bool CanSuggestThisItem => true; - public override bool RequiresDataSourceScope => true; public override bool SupportsParamCoercion => false; public override RequiredDataSourcePermissions FunctionPermission => RequiredDataSourcePermissions.Delete; - // Return true if this function affects datasource query options. - public override bool AffectsDataSourceQueryOptions => true; - public override bool MutatesArg(int argIndex, TexlNode arg) => argIndex == 0; - public override bool ArgMatchesDatasourceType(int argNum) - { - return argNum >= 1; - } - public override bool TryGetTypeForArgSuggestionAt(int argIndex, out DType type) { if (argIndex > 0) @@ -59,8 +49,73 @@ public override bool TryGetTypeForArgSuggestionAt(int argIndex, out DType type) return base.TryGetTypeForArgSuggestionAt(argIndex, out type); } + public RemoveBaseFunction(int arityMax, params DType[] paramTypes) + : base("Remove", TexlStrings.AboutRemove, FunctionCategories.Behavior, DType.EmptyTable, 0, 2, arityMax, paramTypes) + { + } + + public override bool IsLazyEvalParam(TexlNode node, int index, Features features) + { + // First argument to mutation functions is Lazy for datasources that are copy-on-write. + // If there are any side effects in the arguments, we want those to have taken place before we make the copy. + return index == 0; + } + + public override void CheckSemantics(TexlBinding binding, TexlNode[] args, DType[] argTypes, IErrorContainer errors) + { + base.CheckSemantics(binding, args, argTypes, errors); + base.ValidateArgumentIsMutable(binding, args[0], errors); + MutationUtils.CheckSemantics(binding, this, args, argTypes, errors); + } + + public override IEnumerable GetIdentifierOfModifiedValue(TexlNode[] args, out TexlNode identifierNode) + { + Contracts.AssertValue(args); + + identifierNode = null; + if (args.Length == 0) + { + return null; + } + + var firstNameNode = args[0]?.AsFirstName(); + identifierNode = firstNameNode; + if (firstNameNode == null) + { + return null; + } + + var identifiers = new List + { + firstNameNode.Ident + }; + return identifiers; + } + + public override bool IsAsyncInvocation(CallNode callNode, TexlBinding binding) + { + Contracts.AssertValue(callNode); + Contracts.AssertValue(binding); + + return Arg0RequiresAsync(callNode, binding); + } + } + + // Remove(collection:*[], item1:![], item2:![], ..., ["All"]) + internal class RemoveFunction : RemoveBaseFunction, ISuggestionAwareFunction + { + public bool CanSuggestThisItem => true; + + // Return true if this function affects datasource query options. + public override bool AffectsDataSourceQueryOptions => true; + + public override bool ArgMatchesDatasourceType(int argNum) + { + return argNum >= 1; + } + public RemoveFunction() - : base("Remove", TexlStrings.AboutRemove, FunctionCategories.Behavior, DType.EmptyTable, 0, 2, int.MaxValue, DType.EmptyTable) + : base(int.MaxValue, DType.EmptyTable) { } @@ -86,13 +141,6 @@ public override IEnumerable GetRequiredEnumNames() return new List() { LanguageConstants.RemoveFlagsEnumString }; } - public override bool IsLazyEvalParam(TexlNode node, int index, Features features) - { - // First argument to mutation functions is Lazy for datasources that are copy-on-write. - // If there are any side effects in the arguments, we want those to have taken place before we make the copy. - return index == 0; - } - public override bool CheckTypes(CheckTypesContext context, TexlNode[] args, DType[] argTypes, IErrorContainer errors, out DType returnType, out Dictionary nodeToCoercedTypeMap) { Contracts.AssertValue(args); @@ -159,13 +207,6 @@ public override bool CheckTypes(CheckTypesContext context, TexlNode[] args, DTyp return fValid; } - public override void CheckSemantics(TexlBinding binding, TexlNode[] args, DType[] argTypes, IErrorContainer errors) - { - base.CheckSemantics(binding, args, argTypes, errors); - base.ValidateArgumentIsMutable(binding, args[0], errors); - MutationUtils.CheckSemantics(binding, this, args, argTypes, errors); - } - // This method returns true if there are special suggestions for a particular parameter of the function. public override bool HasSuggestionsForParam(int argumentIndex) { @@ -174,30 +215,6 @@ public override bool HasSuggestionsForParam(int argumentIndex) return argumentIndex != 1; } - public override IEnumerable GetIdentifierOfModifiedValue(TexlNode[] args, out TexlNode identifierNode) - { - Contracts.AssertValue(args); - - identifierNode = null; - if (args.Length == 0) - { - return null; - } - - var firstNameNode = args[0]?.AsFirstName(); - identifierNode = firstNameNode; - if (firstNameNode == null) - { - return null; - } - - var identifiers = new List - { - firstNameNode.Ident - }; - return identifiers; - } - /// /// As Remove uses the source record in it's entirity to find the entry in table, uses deepcompare at runtime, we need all fields from source. /// So update the selects for all columns in the source in this case except when datasource is pageable. @@ -277,14 +294,6 @@ public override bool IsSuggestionTypeValid(int paramIndex, DType type) return type.IsRecord || type.Kind == DKind.String; } - public override bool IsAsyncInvocation(CallNode callNode, TexlBinding binding) - { - Contracts.AssertValue(callNode); - Contracts.AssertValue(binding); - - return Arg0RequiresAsync(callNode, binding); - } - protected override bool RequiresPagedDataForParamCore(TexlNode[] args, int paramIndex, TexlBinding binding) { Contracts.AssertValue(args); @@ -299,29 +308,15 @@ protected override bool RequiresPagedDataForParamCore(TexlNode[] args, int param } // Remove(collection:*[], source:*[], ["All"]) - internal class RemoveAllFunction : BuiltinFunction + internal class RemoveAllFunction : RemoveBaseFunction { - public override bool ManipulatesCollections => true; - - public override bool ModifiesValues => true; - - public override bool IsSelfContained => false; - - public override bool RequiresDataSourceScope => true; - - public override bool SupportsParamCoercion => false; - - public override RequiredDataSourcePermissions FunctionPermission => RequiredDataSourcePermissions.Delete; - - public override bool MutatesArg(int argIndex, TexlNode arg) => argIndex == 0; - public override bool ArgMatchesDatasourceType(int argNum) { return argNum == 1; } public RemoveAllFunction() - : base("Remove", TexlStrings.AboutRemove, FunctionCategories.Behavior, DType.EmptyTable, 0, 2, 3, DType.EmptyTable, DType.EmptyTable) + : base(3, DType.EmptyTable, DType.EmptyTable) { } @@ -336,13 +331,6 @@ public override IEnumerable GetRequiredEnumNames() return new List() { LanguageConstants.RemoveFlagsEnumString }; } - public override bool IsLazyEvalParam(TexlNode node, int index, Features features) - { - // First argument to mutation functions is Lazy for datasources that are copy-on-write. - // If there are any side effects in the arguments, we want those to have taken place before we make the copy. - return index == 0; - } - public override bool CheckTypes(CheckTypesContext context, TexlNode[] args, DType[] argTypes, IErrorContainer errors, out DType returnType, out Dictionary nodeToCoercedTypeMap) { Contracts.AssertValue(args); @@ -393,13 +381,6 @@ public override bool CheckTypes(CheckTypesContext context, TexlNode[] args, DTyp return fValid; } - public override void CheckSemantics(TexlBinding binding, TexlNode[] args, DType[] argTypes, IErrorContainer errors) - { - base.CheckSemantics(binding, args, argTypes, errors); - base.ValidateArgumentIsMutable(binding, args[0], errors); - MutationUtils.CheckSemantics(binding, this, args, argTypes, errors); - } - // This method returns true if there are special suggestions for a particular parameter of the function. public override bool HasSuggestionsForParam(int argumentIndex) { @@ -408,38 +389,6 @@ public override bool HasSuggestionsForParam(int argumentIndex) return argumentIndex == 0; } - public override IEnumerable GetIdentifierOfModifiedValue(TexlNode[] args, out TexlNode identifierNode) - { - Contracts.AssertValue(args); - - identifierNode = null; - if (args.Length == 0) - { - return null; - } - - var firstNameNode = args[0]?.AsFirstName(); - identifierNode = firstNameNode; - if (firstNameNode == null) - { - return null; - } - - var identifiers = new List - { - firstNameNode.Ident - }; - return identifiers; - } - - public override bool IsAsyncInvocation(CallNode callNode, TexlBinding binding) - { - Contracts.AssertValue(callNode); - Contracts.AssertValue(binding); - - return Arg0RequiresAsync(callNode, binding); - } - public override bool IsServerDelegatable(CallNode callNode, TexlBinding binding) { Contracts.AssertValue(callNode); diff --git a/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/MutationScripts/Remove.txt b/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/MutationScripts/Remove.txt index 4fb012cb4b..7d7965b101 100644 --- a/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/MutationScripts/Remove.txt +++ b/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/MutationScripts/Remove.txt @@ -27,6 +27,9 @@ Table({a:true,b:"hello",c:DateTime(2024,1,1,0,0,0,0)},{a:true,b:"hello",c:DateTi >> Remove(t1, {a:true}) Errors: Error 0-6: The function 'Remove' has some invalid arguments.|Error 11-19: Missing column. Your formula is missing a column 'b' with a type of 'Text'. +>> Remove(t1, {a:true,b:true}) +Errors: Error 0-6: The function 'Remove' has some invalid arguments.|Error 11-26: Incompatible type. The 'b' column in the data source you’re updating expects a 'Text' type and you’re using a 'Boolean' type. + >> 2;t1 Table({a:true,b:"hello",c:DateTime(2024,1,1,0,0,0,0)},{a:true,b:"hello",c:DateTime(2024,1,1,0,0,0,0)},{a:true,b:"hello",c:DateTime(2024,1,1,0,0,0,0)},{a:true,b:"hi",c:DateTime(2024,1,1,0,0,0,0)},{a:false,b:"hello",c:DateTime(2024,1,1,0,0,0,0)},{a:false,b:"hi",c:DateTime(2024,1,1,0,0,0,0)})