protected bool IsValidNode(TexlNode node, TexlBinding binding) { Contracts.AssertValue(node); Contracts.AssertValue(binding); bool isAsync = binding.IsAsync(node); bool isPure = binding.IsPure(node); if (node is DottedNameNode && ((binding.GetType(node.AsDottedName().Left).Kind == DKind.OptionSet && binding.GetType(node).Kind == DKind.OptionSetValue) || (binding.GetType(node.AsDottedName().Left).Kind == DKind.View && binding.GetType(node).Kind == DKind.ViewValue))) { // OptionSet and View Access are delegable despite being async return(true); } if (node is CallNode && (binding.IsBlockScopedConstant(node) || (binding.GetInfo(node as CallNode).Function is AsTypeFunction))) { // AsType is delegable despite being async return(true); } // Async predicates and impure nodes are not supported. // Let CallNodes for User() be marked as being Valid to allow // expressions with User() calls to be delegated if (!(IsUserCallNodeDelegable(node, binding)) && (isAsync || !isPure)) { var telemetryMessage = string.Format("Kind:{0}, isAsync:{1}, isPure:{2}", node.Kind, isAsync, isPure); SuggestDelegationHintAndAddTelemetryMessage(node, binding, telemetryMessage); if (isAsync) { TrackingProvider.Instance.SetDelegationTrackerStatus(DelegationStatus.AsyncPredicate, node, binding, _function); } if (!isPure) { TrackingProvider.Instance.SetDelegationTrackerStatus(DelegationStatus.ImpureNode, node, binding, _function, DelegationTelemetryInfo.CreateImpureNodeTelemetryInfo(node, binding)); } return(false); } return(true); }