public override bool IsServerDelegatable(CallNode callNode, TexlBinding binding)
        {
            Contracts.AssertValue(callNode);
            Contracts.AssertValue(binding);

            if (FunctionDelegationCapability.Capabilities == DelegationCapability.None)
            {
                return(false);
            }

            if (!CheckArgsCount(callNode, binding))
            {
                return(false);
            }

            IExternalDataSource dataSource;

            if (!TryGetValidDataSourceForDelegation(callNode, binding, FunctionDelegationCapability, out dataSource))
            {
                if (dataSource != null && dataSource.IsDelegatable)
                {
                    binding.ErrorContainer.EnsureError(DocumentErrorSeverity.Warning, callNode, TexlStrings.OpNotSupportedByServiceSuggestionMessage_OpNotSupportedByService, Name);
                }

                return(false);
            }

            var args = callNode.Args.Children.VerifyValue();

            if (binding.GetType(args[0]).HasExpandInfo ||
                (!binding.IsFullRecordRowScopeAccess(args[1]) && args[1].Kind != NodeKind.FirstName) ||
                !binding.IsRowScope(args[1]) ||
                binding.GetType(args[1]) != DType.Number ||
                ExpressionContainsView(callNode, binding))
            {
                SuggestDelegationHint(callNode, binding);

                if (binding.GetType(args[1]) != DType.Number)
                {
                    DelegationTrackerCore.SetDelegationTrackerStatus(DelegationStatus.NotANumberArgType, callNode, binding, this, DelegationTelemetryInfo.CreateEmptyDelegationTelemetryInfo());
                }
                else
                {
                    DelegationTrackerCore.SetDelegationTrackerStatus(DelegationStatus.InvalidArgType, callNode, binding, this, DelegationTelemetryInfo.CreateEmptyDelegationTelemetryInfo());
                }

                return(false);
            }

            if (binding.IsFullRecordRowScopeAccess(args[1]))
            {
                return(GetDottedNameNodeDelegationStrategy().IsValidDottedNameNode(args[1].AsDottedName(), binding, null, null));
            }

            var firstNameStrategy = GetFirstNameNodeDelegationStrategy().VerifyValue();

            return(firstNameStrategy.IsValidFirstNameNode(args[1].AsFirstName(), binding, null));
        }
Example #2
0
        public static void LogTelemetryForFunction(TexlFunction function, CallNode node, TexlBinding texlBinding,
                                                   bool isServerDelegatable)
        {
            Contracts.AssertValue(function);
            Contracts.AssertValue(node);
            Contracts.AssertValue(texlBinding);

            // We only want to log about successful delegation status here. Any failures should have been logged by this time.
            if (isServerDelegatable)
            {
                DelegationTrackerCore.SetDelegationTrackerStatus(DelegationStatus.DelegationSuccessful, node, texlBinding, function);
                return;
            }
        }
Example #3
0
        private bool IsSortOrderSuppportedByColumn(TexlNode node, TexlBinding binding, string order, SortOpMetadata metadata, DPath columnPath)
        {
            Contracts.AssertValue(node);
            Contracts.AssertValue(binding);
            Contracts.AssertValue(order);
            Contracts.AssertValue(metadata);
            Contracts.AssertValid(columnPath);

            var result = IsSortOrderSuppportedByColumn(order, metadata, columnPath);

            if (!result)
            {
                DelegationTrackerCore.SetDelegationTrackerStatus(DelegationStatus.SortOrderNotSupportedByColumn, node, binding, this, DelegationTelemetryInfo.CreateEmptyDelegationTelemetryInfo());
            }

            return(result);
        }
Example #4
0
        private bool IsValidSortOrderNode(TexlNode node, SortOpMetadata metadata, TexlBinding binding, DPath columnPath)
        {
            Contracts.AssertValue(node);
            Contracts.AssertValue(metadata);
            Contracts.AssertValue(binding);
            Contracts.AssertValid(columnPath);

            if (binding.IsAsync(node))
            {
                AddSuggestionMessageToTelemetry("Async sortorder node.", node, binding);
                DelegationTrackerCore.SetDelegationTrackerStatus(DelegationStatus.AsyncSortOrder, node, binding, this, DelegationTelemetryInfo.CreateEmptyDelegationTelemetryInfo());
                return(false);
            }

            string sortOrder;

            switch (node.Kind)
            {
            case NodeKind.FirstName:
            case NodeKind.StrLit:
                return(_sortOrderValidator.TryGetValidValue(node, binding, out sortOrder) &&
                       IsSortOrderSuppportedByColumn(node, binding, sortOrder, metadata, columnPath));

            case NodeKind.DottedName:
            case NodeKind.Call:
                if (_sortOrderValidator.TryGetValidValue(node, binding, out sortOrder) &&
                    IsSortOrderSuppportedByColumn(node, binding, sortOrder, metadata, columnPath))
                {
                    return(true);
                }

                // If both ascending and descending are supported then we can support this.
                return(IsSortOrderSuppportedByColumn(node, binding, LanguageConstants.DescendingSortOrderString, metadata, columnPath) &&
                       IsSortOrderSuppportedByColumn(node, binding, LanguageConstants.AscendingSortOrderString, metadata, columnPath));

            default:
                AddSuggestionMessageToTelemetry("Unsupported sortorder node kind.", node, binding);
                return(false);
            }
        }
Example #5
0
        public override bool IsServerDelegatable(CallNode callNode, TexlBinding binding)
        {
            Contracts.AssertValue(callNode);
            Contracts.AssertValue(binding);

            if (!CheckArgsCount(callNode, binding))
            {
                return(false);
            }

            SortOpMetadata      metadata           = null;
            IDelegationMetadata delegationMetadata = null;
            IExternalDataSource dataSource;

            if (TryGetEntityMetadata(callNode, binding, out delegationMetadata))
            {
                if (!binding.Document.Properties.EnabledFeatures.IsEnhancedDelegationEnabled ||
                    !TryGetValidDataSourceForDelegation(callNode, binding, DelegationCapability.ArrayLookup, out _))
                {
                    SuggestDelegationHint(callNode, binding);
                    return(false);
                }

                metadata = delegationMetadata.SortDelegationMetadata.VerifyValue();
            }
            else
            {
                if (!TryGetValidDataSourceForDelegation(callNode, binding, DelegationCapability.Sort, out dataSource))
                {
                    return(false);
                }

                metadata = dataSource.DelegationMetadata.SortDelegationMetadata;
            }

            TexlNode[] args = callNode.Args.Children.VerifyValue();
            TexlNode   arg1 = args[1].VerifyValue();

            // For now, we are only supporting delegation for Sort operations where second argument is column name.
            // For example, Sort(CDS, Value)
            FirstNameNode firstName = arg1.AsFirstName();

            if (firstName == null)
            {
                SuggestDelegationHint(arg1, binding);
                AddSuggestionMessageToTelemetry("Arg1 is not a FirstName node.", arg1, binding);
                DelegationTrackerCore.SetDelegationTrackerStatus(DelegationStatus.UnSupportedSortArg, arg1, binding, this, DelegationTelemetryInfo.CreateEmptyDelegationTelemetryInfo());
                return(false);
            }

            FirstNameInfo firstNameInfo = binding.GetInfo(firstName);

            if (firstNameInfo == null)
            {
                return(false);
            }

            DPath columnName = DPath.Root.Append(firstNameInfo.Name);

            if (!metadata.IsDelegationSupportedByColumn(columnName, DelegationCapability.Sort))
            {
                SuggestDelegationHint(firstName, binding);
                DelegationTrackerCore.SetDelegationTrackerStatus(DelegationStatus.NoDelSupportByColumn, firstName, binding, this, DelegationTelemetryInfo.CreateNoDelSupportByColumnTelemetryInfo(firstNameInfo));
                return(false);
            }

            const string defaultSortOrder = LanguageConstants.AscendingSortOrderString;
            int          cargs            = args.Count();

            // Verify that the third argument (If present) is an Enum or string literal.
            if (cargs < 3 && IsSortOrderSuppportedByColumn(callNode, binding, defaultSortOrder, metadata, columnName))
            {
                return(true);
            }

            // TASK: 6237100 - Binder: Propagate errors in subtree of the callnode to the call node itself
            // Only FirstName, DottedName and StrLit non-async nodes are supported for arg2.
            TexlNode arg2 = args[2].VerifyValue();

            if (!IsValidSortOrderNode(arg2, metadata, binding, columnName))
            {
                SuggestDelegationHint(arg2, binding);
                return(false);
            }

            return(true);
        }