33
44using System . Collections . Generic ;
55using System . Linq ;
6+ using System . Numerics ;
67using Microsoft . PowerFx . Core . App . ErrorContainers ;
78using Microsoft . PowerFx . Core . Binding ;
89using Microsoft . PowerFx . Core . Entities ;
1920
2021namespace Microsoft . PowerFx . Core . Texl . Builtins
2122{
22- // Remove(collection:*[], item1:![], item2:![], ..., ["All"])
23- internal class RemoveFunction : BuiltinFunction , ISuggestionAwareFunction
23+ internal abstract class RemoveBaseFunction : BuiltinFunction
2424 {
2525 public override bool ManipulatesCollections => true ;
2626
@@ -30,24 +30,14 @@ internal class RemoveFunction : BuiltinFunction, ISuggestionAwareFunction
3030
3131 public override bool IsSelfContained => false ;
3232
33- public bool CanSuggestThisItem => true ;
34-
3533 public override bool RequiresDataSourceScope => true ;
3634
3735 public override bool SupportsParamCoercion => false ;
3836
3937 public override RequiredDataSourcePermissions FunctionPermission => RequiredDataSourcePermissions . Delete ;
4038
41- // Return true if this function affects datasource query options.
42- public override bool AffectsDataSourceQueryOptions => true ;
43-
4439 public override bool MutatesArg ( int argIndex , TexlNode arg ) => argIndex == 0 ;
4540
46- public override bool ArgMatchesDatasourceType ( int argNum )
47- {
48- return argNum >= 1 ;
49- }
50-
5141 public override bool TryGetTypeForArgSuggestionAt ( int argIndex , out DType type )
5242 {
5343 if ( argIndex > 0 )
@@ -59,8 +49,73 @@ public override bool TryGetTypeForArgSuggestionAt(int argIndex, out DType type)
5949 return base . TryGetTypeForArgSuggestionAt ( argIndex , out type ) ;
6050 }
6151
52+ public RemoveBaseFunction ( int arityMax , params DType [ ] paramTypes )
53+ : base ( "Remove" , TexlStrings . AboutRemove , FunctionCategories . Behavior , DType . EmptyTable , 0 , 2 , arityMax , paramTypes )
54+ {
55+ }
56+
57+ public override bool IsLazyEvalParam ( TexlNode node , int index , Features features )
58+ {
59+ // First argument to mutation functions is Lazy for datasources that are copy-on-write.
60+ // If there are any side effects in the arguments, we want those to have taken place before we make the copy.
61+ return index == 0 ;
62+ }
63+
64+ public override void CheckSemantics ( TexlBinding binding , TexlNode [ ] args , DType [ ] argTypes , IErrorContainer errors )
65+ {
66+ base . CheckSemantics ( binding , args , argTypes , errors ) ;
67+ base . ValidateArgumentIsMutable ( binding , args [ 0 ] , errors ) ;
68+ MutationUtils . CheckSemantics ( binding , this , args , argTypes , errors ) ;
69+ }
70+
71+ public override IEnumerable < Identifier > GetIdentifierOfModifiedValue ( TexlNode [ ] args , out TexlNode identifierNode )
72+ {
73+ Contracts . AssertValue ( args ) ;
74+
75+ identifierNode = null ;
76+ if ( args . Length == 0 )
77+ {
78+ return null ;
79+ }
80+
81+ var firstNameNode = args [ 0 ] ? . AsFirstName ( ) ;
82+ identifierNode = firstNameNode ;
83+ if ( firstNameNode == null )
84+ {
85+ return null ;
86+ }
87+
88+ var identifiers = new List < Identifier >
89+ {
90+ firstNameNode . Ident
91+ } ;
92+ return identifiers ;
93+ }
94+
95+ public override bool IsAsyncInvocation ( CallNode callNode , TexlBinding binding )
96+ {
97+ Contracts . AssertValue ( callNode ) ;
98+ Contracts . AssertValue ( binding ) ;
99+
100+ return Arg0RequiresAsync ( callNode , binding ) ;
101+ }
102+ }
103+
104+ // Remove(collection:*[], item1:![], item2:![], ..., ["All"])
105+ internal class RemoveFunction : RemoveBaseFunction , ISuggestionAwareFunction
106+ {
107+ public bool CanSuggestThisItem => true ;
108+
109+ // Return true if this function affects datasource query options.
110+ public override bool AffectsDataSourceQueryOptions => true ;
111+
112+ public override bool ArgMatchesDatasourceType ( int argNum )
113+ {
114+ return argNum >= 1 ;
115+ }
116+
62117 public RemoveFunction ( )
63- : base ( "Remove" , TexlStrings . AboutRemove , FunctionCategories . Behavior , DType . EmptyTable , 0 , 2 , int . MaxValue , DType . EmptyTable )
118+ : base ( int . MaxValue , DType . EmptyTable )
64119 {
65120 }
66121
@@ -86,13 +141,6 @@ public override IEnumerable<string> GetRequiredEnumNames()
86141 return new List < string > ( ) { LanguageConstants . RemoveFlagsEnumString } ;
87142 }
88143
89- public override bool IsLazyEvalParam ( TexlNode node , int index , Features features )
90- {
91- // First argument to mutation functions is Lazy for datasources that are copy-on-write.
92- // If there are any side effects in the arguments, we want those to have taken place before we make the copy.
93- return index == 0 ;
94- }
95-
96144 public override bool CheckTypes ( CheckTypesContext context , TexlNode [ ] args , DType [ ] argTypes , IErrorContainer errors , out DType returnType , out Dictionary < TexlNode , DType > nodeToCoercedTypeMap )
97145 {
98146 Contracts . AssertValue ( args ) ;
@@ -159,13 +207,6 @@ public override bool CheckTypes(CheckTypesContext context, TexlNode[] args, DTyp
159207 return fValid ;
160208 }
161209
162- public override void CheckSemantics ( TexlBinding binding , TexlNode [ ] args , DType [ ] argTypes , IErrorContainer errors )
163- {
164- base . CheckSemantics ( binding , args , argTypes , errors ) ;
165- base . ValidateArgumentIsMutable ( binding , args [ 0 ] , errors ) ;
166- MutationUtils . CheckSemantics ( binding , this , args , argTypes , errors ) ;
167- }
168-
169210 // This method returns true if there are special suggestions for a particular parameter of the function.
170211 public override bool HasSuggestionsForParam ( int argumentIndex )
171212 {
@@ -174,30 +215,6 @@ public override bool HasSuggestionsForParam(int argumentIndex)
174215 return argumentIndex != 1 ;
175216 }
176217
177- public override IEnumerable < Identifier > GetIdentifierOfModifiedValue ( TexlNode [ ] args , out TexlNode identifierNode )
178- {
179- Contracts . AssertValue ( args ) ;
180-
181- identifierNode = null ;
182- if ( args . Length == 0 )
183- {
184- return null ;
185- }
186-
187- var firstNameNode = args [ 0 ] ? . AsFirstName ( ) ;
188- identifierNode = firstNameNode ;
189- if ( firstNameNode == null )
190- {
191- return null ;
192- }
193-
194- var identifiers = new List < Identifier >
195- {
196- firstNameNode . Ident
197- } ;
198- return identifiers ;
199- }
200-
201218 /// <summary>
202219 /// 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.
203220 /// 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)
277294 return type . IsRecord || type . Kind == DKind . String ;
278295 }
279296
280- public override bool IsAsyncInvocation ( CallNode callNode , TexlBinding binding )
281- {
282- Contracts . AssertValue ( callNode ) ;
283- Contracts . AssertValue ( binding ) ;
284-
285- return Arg0RequiresAsync ( callNode , binding ) ;
286- }
287-
288297 protected override bool RequiresPagedDataForParamCore ( TexlNode [ ] args , int paramIndex , TexlBinding binding )
289298 {
290299 Contracts . AssertValue ( args ) ;
@@ -299,29 +308,15 @@ protected override bool RequiresPagedDataForParamCore(TexlNode[] args, int param
299308 }
300309
301310 // Remove(collection:*[], source:*[], ["All"])
302- internal class RemoveAllFunction : BuiltinFunction
311+ internal class RemoveAllFunction : RemoveBaseFunction
303312 {
304- public override bool ManipulatesCollections => true ;
305-
306- public override bool ModifiesValues => true ;
307-
308- public override bool IsSelfContained => false ;
309-
310- public override bool RequiresDataSourceScope => true ;
311-
312- public override bool SupportsParamCoercion => false ;
313-
314- public override RequiredDataSourcePermissions FunctionPermission => RequiredDataSourcePermissions . Delete ;
315-
316- public override bool MutatesArg ( int argIndex , TexlNode arg ) => argIndex == 0 ;
317-
318313 public override bool ArgMatchesDatasourceType ( int argNum )
319314 {
320315 return argNum == 1 ;
321316 }
322317
323318 public RemoveAllFunction ( )
324- : base ( "Remove" , TexlStrings . AboutRemove , FunctionCategories . Behavior , DType . EmptyTable , 0 , 2 , 3 , DType . EmptyTable , DType . EmptyTable )
319+ : base ( 3 , DType . EmptyTable , DType . EmptyTable )
325320 {
326321 }
327322
@@ -336,13 +331,6 @@ public override IEnumerable<string> GetRequiredEnumNames()
336331 return new List < string > ( ) { LanguageConstants . RemoveFlagsEnumString } ;
337332 }
338333
339- public override bool IsLazyEvalParam ( TexlNode node , int index , Features features )
340- {
341- // First argument to mutation functions is Lazy for datasources that are copy-on-write.
342- // If there are any side effects in the arguments, we want those to have taken place before we make the copy.
343- return index == 0 ;
344- }
345-
346334 public override bool CheckTypes ( CheckTypesContext context , TexlNode [ ] args , DType [ ] argTypes , IErrorContainer errors , out DType returnType , out Dictionary < TexlNode , DType > nodeToCoercedTypeMap )
347335 {
348336 Contracts . AssertValue ( args ) ;
@@ -393,13 +381,6 @@ public override bool CheckTypes(CheckTypesContext context, TexlNode[] args, DTyp
393381 return fValid ;
394382 }
395383
396- public override void CheckSemantics ( TexlBinding binding , TexlNode [ ] args , DType [ ] argTypes , IErrorContainer errors )
397- {
398- base . CheckSemantics ( binding , args , argTypes , errors ) ;
399- base . ValidateArgumentIsMutable ( binding , args [ 0 ] , errors ) ;
400- MutationUtils . CheckSemantics ( binding , this , args , argTypes , errors ) ;
401- }
402-
403384 // This method returns true if there are special suggestions for a particular parameter of the function.
404385 public override bool HasSuggestionsForParam ( int argumentIndex )
405386 {
@@ -408,38 +389,6 @@ public override bool HasSuggestionsForParam(int argumentIndex)
408389 return argumentIndex == 0 ;
409390 }
410391
411- public override IEnumerable < Identifier > GetIdentifierOfModifiedValue ( TexlNode [ ] args , out TexlNode identifierNode )
412- {
413- Contracts . AssertValue ( args ) ;
414-
415- identifierNode = null ;
416- if ( args . Length == 0 )
417- {
418- return null ;
419- }
420-
421- var firstNameNode = args [ 0 ] ? . AsFirstName ( ) ;
422- identifierNode = firstNameNode ;
423- if ( firstNameNode == null )
424- {
425- return null ;
426- }
427-
428- var identifiers = new List < Identifier >
429- {
430- firstNameNode . Ident
431- } ;
432- return identifiers ;
433- }
434-
435- public override bool IsAsyncInvocation ( CallNode callNode , TexlBinding binding )
436- {
437- Contracts . AssertValue ( callNode ) ;
438- Contracts . AssertValue ( binding ) ;
439-
440- return Arg0RequiresAsync ( callNode , binding ) ;
441- }
442-
443392 public override bool IsServerDelegatable ( CallNode callNode , TexlBinding binding )
444393 {
445394 Contracts . AssertValue ( callNode ) ;
0 commit comments