// Verifies if given kind of node is supported by function delegation. private bool IsSupportedNode(TexlNode node, OperationCapabilityMetadata metadata, TexlBinding binding, IOpDelegationStrategy opDelStrategy, bool isRHSNode) { Contracts.AssertValue(node); Contracts.AssertValue(metadata); Contracts.AssertValue(binding); Contracts.AssertValue(opDelStrategy); if (!binding.IsRowScope(node)) { // Check whether this is - // 1) in operator delegation and // 2) it is verifying if RHS node is supported and // 3) it is not an async node and // 4) it is a single column table and // 5) metadata belongs to cds datasource that supports delegation of CdsIn // If this check fails, verify if it is simply a valid node.. // Eg of valid delegation functions - // Filter(Accounts, 'Account Name' in ["Foo", Bar"]) - Direct table use // Set(Names, ["Foo", Bar"]); Filter(Accounts, 'Account Name' in Names) - Using variable of type table // ClearCollect(Names, Accounts); Filter(Accounts, 'Account Name' in Names.'Account Name') - using column from collection. // This won't be delegated - Filter(Accounts, 'Account Name' in Accounts.'Account Name') as Accounts.'Account Name' is async. if ((binding.Document.Properties.EnabledFeatures.IsEnhancedDelegationEnabled && isRHSNode && (opDelStrategy as BinaryOpDelegationStrategy)?.Op == BinaryOp.In && !binding.IsAsync(node) && binding.GetType(node).IsTable&& binding.GetType(node).IsColumn&& metadata.IsDelegationSupportedByTable(DelegationCapability.CdsIn)) || IsValidNode(node, binding)) { return(true); } } switch (node.Kind) { case NodeKind.DottedName: { if (!opDelStrategy.IsOpSupportedByTable(metadata, node, binding)) { return(false); } var dottedNodeValStrategy = _function.GetDottedNameNodeDelegationStrategy(); return(dottedNodeValStrategy.IsValidDottedNameNode(node.AsDottedName(), binding, metadata, opDelStrategy)); } case NodeKind.Call: { if (!opDelStrategy.IsOpSupportedByTable(metadata, node, binding)) { return(false); } var cNodeValStrategy = _function.GetCallNodeDelegationStrategy(); return(cNodeValStrategy.IsValidCallNode(node.AsCall(), binding, metadata)); } case NodeKind.FirstName: { var firstNameNodeValStrategy = _function.GetFirstNameNodeDelegationStrategy(); return(firstNameNodeValStrategy.IsValidFirstNameNode(node.AsFirstName(), binding, opDelStrategy)); } case NodeKind.UnaryOp: { if (!opDelStrategy.IsOpSupportedByTable(metadata, node, binding)) { return(false); } var unaryopNode = node.AsUnaryOpLit(); IOpDelegationStrategy unaryOpNodeDelegationStrategy = _function.GetOpDelegationStrategy(unaryopNode.Op); return(unaryOpNodeDelegationStrategy.IsSupportedOpNode(unaryopNode, metadata, binding)); } case NodeKind.BinaryOp: { if (!opDelStrategy.IsOpSupportedByTable(metadata, node, binding)) { return(false); } var binaryOpNode = node.AsBinaryOp().VerifyValue(); opDelStrategy = _function.GetOpDelegationStrategy(binaryOpNode.Op, binaryOpNode); var binaryOpDelStrategy = (opDelStrategy as BinaryOpDelegationStrategy).VerifyValue(); Contracts.Assert(binaryOpNode.Op == binaryOpDelStrategy.Op); if (!opDelStrategy.IsSupportedOpNode(node, metadata, binding)) { SuggestDelegationHint(binaryOpNode, binding); return(false); } break; } default: { var kind = node.Kind; if (kind != NodeKind.BoolLit && kind != NodeKind.StrLit && kind != NodeKind.NumLit) { var telemetryMessage = string.Format("NodeKind {0} unsupported.", kind); SuggestDelegationHintAndAddTelemetryMessage(node, binding, telemetryMessage); return(false); } break; } } return(true); }
public override bool IsRowScopedServerDelegatable(CallNode callNode, TexlBinding binding, OperationCapabilityMetadata metadata) { Contracts.AssertValue(callNode); Contracts.AssertValue(binding); Contracts.AssertValue(metadata); if (binding.ErrorContainer.HasErrors(callNode) || !CheckArgsCount(callNode, binding) || !binding.IsRowScope(callNode)) { return(false); } TexlNode[] args = callNode.Args.Children.VerifyValue(); NodeKind argKind = args[0].VerifyValue().Kind; var opStrategy = GetOpDelegationStrategy(UnaryOp.Not); var firstNameStrategy = GetFirstNameNodeDelegationStrategy(); var dottedStrategy = GetDottedNameNodeDelegationStrategy(); var cNodeStrategy = GetCallNodeDelegationStrategy(); switch (argKind) { case NodeKind.FirstName: return(firstNameStrategy.IsValidFirstNameNode(args[0].AsFirstName(), binding, opStrategy)); case NodeKind.Call: { if (!opStrategy.IsOpSupportedByTable(metadata, callNode, binding)) { return(false); } return(cNodeStrategy.IsValidCallNode(args[0].AsCall(), binding, metadata)); } case NodeKind.BinaryOp: { if (!opStrategy.IsOpSupportedByTable(metadata, callNode, binding)) { return(false); } BinaryOpNode opNode = args[0].AsBinaryOp(); IOpDelegationStrategy binaryOpNodeValidationStrategy = GetOpDelegationStrategy(opNode.Op, opNode); return(binaryOpNodeValidationStrategy.IsSupportedOpNode(opNode, metadata, binding)); } case NodeKind.UnaryOp: { if (!opStrategy.IsOpSupportedByTable(metadata, callNode, binding)) { return(false); } UnaryOpNode opNode = args[0].AsUnaryOpLit(); var unaryOpNodeValidationStrategy = GetOpDelegationStrategy(opNode.Op); return(unaryOpNodeValidationStrategy.IsSupportedOpNode(opNode, metadata, binding)); } case NodeKind.DottedName: return(dottedStrategy.IsValidDottedNameNode(args[0].AsDottedName(), binding, metadata, opStrategy)); default: return(argKind == NodeKind.BoolLit); } }
private bool IsSupportedNode(TexlNode node, OperationCapabilityMetadata metadata, TexlBinding binding, IOpDelegationStrategy opDelStrategy) { Contracts.AssertValue(node); Contracts.AssertValue(metadata); Contracts.AssertValue(binding); Contracts.AssertValue(opDelStrategy); if (!binding.IsRowScope(node)) { return(true); } switch (node.Kind) { case NodeKind.DottedName: { if (!opDelStrategy.IsOpSupportedByTable(metadata, node, binding)) { return(false); } var dottedNodeValStrategy = _function.GetDottedNameNodeDelegationStrategy(); return(dottedNodeValStrategy.IsValidDottedNameNode(node.AsDottedName(), binding, metadata, opDelStrategy)); } case NodeKind.Call: { if (!opDelStrategy.IsOpSupportedByTable(metadata, node, binding)) { return(false); } var cNodeValStrategy = _function.GetCallNodeDelegationStrategy(); return(cNodeValStrategy.IsValidCallNode(node.AsCall(), binding, metadata)); } case NodeKind.FirstName: { var firstNameNodeValStrategy = _function.GetFirstNameNodeDelegationStrategy(); return(firstNameNodeValStrategy.IsValidFirstNameNode(node.AsFirstName(), binding, opDelStrategy)); } case NodeKind.UnaryOp: { if (!opDelStrategy.IsOpSupportedByTable(metadata, node, binding)) { return(false); } UnaryOpNode unaryOpNode = node.AsUnaryOpLit().VerifyValue(); opDelStrategy = _function.GetOpDelegationStrategy(unaryOpNode.Op).VerifyValue(); var unaryOpDelStrategy = (opDelStrategy as UnaryOpDelegationStrategy).VerifyValue(); Contracts.Assert(unaryOpDelStrategy.Op == unaryOpNode.Op); if (!opDelStrategy.IsSupportedOpNode(node, metadata, binding)) { SuggestDelegationHint(node, binding); return(false); } return(true); } case NodeKind.BinaryOp: { if (!opDelStrategy.IsOpSupportedByTable(metadata, node, binding)) { return(false); } var binaryOpNode = node.AsBinaryOp().VerifyValue(); IOpDelegationStrategy binaryOpNodeDelValidationStrategy = _function.GetOpDelegationStrategy(binaryOpNode.Op, binaryOpNode); return(binaryOpNodeDelValidationStrategy.IsSupportedOpNode(node.AsBinaryOp(), metadata, binding)); } } SuggestDelegationHint(node, binding); return(false); }