public bool TryGetValidValue(TexlNode argNode, TexlBinding binding, out IList <FirstNameNode> dsNodes) { Contracts.AssertValue(argNode); Contracts.AssertValue(binding); dsNodes = new List <FirstNameNode>(); FirstNameNode dsNode; switch (argNode.Kind) { case NodeKind.FirstName: if (TryGetDsNode(argNode.AsFirstName(), binding, out dsNode)) { dsNodes.Add(dsNode); } break; case NodeKind.Call: return(TryGetDsNodes(argNode.AsCall(), binding, out dsNodes)); case NodeKind.DottedName: return(TryGetDsNode(argNode.AsDottedName(), binding, out dsNodes)); } return(dsNodes.Count > 0); }
// Gets the inner most function and the current arg index from the current node, if any. // If there is no inner most function, current arg index will be -1 // and argument count will be -1. internal static bool TryGetInnerMostFunction(TexlNode nodeCur, TexlBinding bind, out TexlFunction funcCur, out int iarg, out int carg) { Contracts.AssertValue(nodeCur); Contracts.AssertValue(bind); TexlNode nodeParent = nodeCur.Parent; TexlNode nodeCallArg = nodeCur; CallNode callNode = null; while (nodeParent != null) { if (nodeParent.Kind == NodeKind.Call) { callNode = nodeParent.AsCall(); break; } // The last node before a call's list node is the call arg. if (nodeParent.Kind != NodeKind.List) { nodeCallArg = nodeParent; } nodeParent = nodeParent.Parent; } if (callNode == null) { iarg = -1; carg = -1; funcCur = null; return(false); } Contracts.AssertValue(nodeCallArg); CallInfo info = bind.GetInfo(callNode); if (info.Function != null) { carg = callNode.Args.Count; for (iarg = 0; iarg < carg; iarg++) { if (callNode.Args.Children[iarg] == nodeCallArg) { break; } } Contracts.Assert(iarg < carg); funcCur = (TexlFunction)info.Function; return(true); } iarg = -1; carg = -1; funcCur = null; return(false); }
public static DelegationTelemetryInfo CreateImpureNodeTelemetryInfo(TexlNode node, TexlBinding binding = null) { Contracts.AssertValue(node); Contracts.AssertValueOrNull(binding); switch (node.Kind) { case NodeKind.Call: var callNode = node.AsCall(); var funcName = binding?.GetInfo(callNode)?.Function?.Name ?? string.Empty; return(new DelegationTelemetryInfo(funcName)); default: return(new DelegationTelemetryInfo(node.ToString())); } }
private static CallNode GetNearestCallNode(TexlNode node) { Contracts.AssertValue(node); TexlNode parent = node; while (parent != null) { CallNode callNode; if ((callNode = parent.AsCall()) != null) { return(callNode); } parent = parent.Parent; } return(null); }
public bool TryGetValidValue(TexlNode argNode, TexlBinding binding, out IExpandInfo entityInfo) { Contracts.AssertValue(argNode); Contracts.AssertValue(binding); entityInfo = null; switch (argNode.Kind) { case NodeKind.FirstName: return(TryGetEntityInfo(argNode.AsFirstName(), binding, out entityInfo)); case NodeKind.Call: return(TryGetEntityInfo(argNode.AsCall(), binding, out entityInfo)); case NodeKind.DottedName: return(TryGetEntityInfo(argNode.AsDottedName(), binding, out entityInfo)); } return(false); }
public bool TryGetValidValue(TexlNode argNode, TexlBinding binding, out IExternalDataSource dsInfo) { Contracts.AssertValue(argNode); Contracts.AssertValue(binding); dsInfo = null; switch (argNode.Kind) { case NodeKind.FirstName: return(TryGetDsInfo(argNode.AsFirstName(), binding, out dsInfo)); case NodeKind.Call: return(TryGetDsInfo(argNode.AsCall(), binding, out dsInfo)); case NodeKind.DottedName: return(TryGetDsInfo(argNode.AsDottedName(), binding, out dsInfo)); case NodeKind.As: return(TryGetValidValue(argNode.AsAsNode().Left, binding, out dsInfo)); } return(false); }
// 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); }
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); }
protected bool IsValidDelegatableFilterPredicateNode(TexlNode dsNode, TexlBinding binding, FilterOpMetadata filterMetadata) { Contracts.AssertValue(dsNode); Contracts.AssertValue(binding); Contracts.AssertValue(filterMetadata); var firstNameStrategy = GetFirstNameNodeDelegationStrategy(); var dottedNameStrategy = GetDottedNameNodeDelegationStrategy(); var cNodeStrategy = GetCallNodeDelegationStrategy(); NodeKind kind; kind = dsNode.Kind; switch (kind) { case NodeKind.BinaryOp: { BinaryOpNode opNode = dsNode.AsBinaryOp(); var binaryOpNodeValidationStrategy = GetOpDelegationStrategy(opNode.Op, opNode); Contracts.AssertValue(opNode); if (!binaryOpNodeValidationStrategy.IsSupportedOpNode(opNode, filterMetadata, binding)) { return(false); } break; } case NodeKind.FirstName: { if (!firstNameStrategy.IsValidFirstNameNode(dsNode.AsFirstName(), binding, null)) { return(false); } break; } case NodeKind.DottedName: { if (!dottedNameStrategy.IsValidDottedNameNode(dsNode.AsDottedName(), binding, filterMetadata, null)) { return(false); } break; } case NodeKind.UnaryOp: { UnaryOpNode opNode = dsNode.AsUnaryOpLit(); var unaryOpNodeValidationStrategy = GetOpDelegationStrategy(opNode.Op); Contracts.AssertValue(opNode); if (!unaryOpNodeValidationStrategy.IsSupportedOpNode(opNode, filterMetadata, binding)) { SuggestDelegationHint(dsNode, binding); return(false); } break; } case NodeKind.Call: { if (!cNodeStrategy.IsValidCallNode(dsNode.AsCall(), binding, filterMetadata)) { return(false); } break; } default: { if (kind != NodeKind.BoolLit) { SuggestDelegationHint(dsNode, binding, string.Format("Not supported node {0}.", kind)); return(false); } break; } } return(true); }