示例#1
0
        /// <summary>
        /// Look up an enum value by its locale-specific name.
        /// For example, locName="Droit" --> invName="Right", value="right"
        /// </summary>
        public bool TryLookupValueByLocName(string locName, out string invName, out object value)
        {
            Contracts.AssertValue(locName);
            Contracts.Assert(DName.IsValidDName(locName));

            if (!_valuesLocToInvariant.TryGetValue(locName, out invName))
            {
                value = null;
                return(false);
            }

            return(EnumType.TryGetEnumValue(new DName(invName), out value));
        }
示例#2
0
        public CallInfo(TexlFunction function, CallNode node, DType cursorType, DName scopeIdentifier, bool requiresScopeIdentifier, int scopeNest)
        {
            Contracts.AssertValue(function);
            Contracts.AssertValue(node);
            Contracts.Assert(scopeNest >= 0);

            Function                = function;
            Node                    = node;
            CursorType              = cursorType;
            ScopeNest               = scopeNest;
            ScopeIdentifier         = scopeIdentifier;
            RequiresScopeIdentifier = requiresScopeIdentifier;
        }
示例#3
0
        public virtual bool LookupEnumValueByTypeAndLocName(DType enumType, DName locName, out object value)
        {
            // Slower O(n) lookup involving a walk over the registered enums...
            foreach (var info in _enums)
            {
                if (info.EnumType == enumType)
                {
                    return(info.TryLookupValueByLocName(locName.Value, out _, out value));
                }
            }

            value = null;
            return(false);
        }
示例#4
0
        private FirstNameInfo(BindKind kind, FirstNameNode node, int nestDst, int nestCur, DPath path, object data, DName dataControlName, bool isDataControlAccess)
            : base(kind, node)
        {
            Contracts.Assert(nestDst >= int.MinValue);
            Contracts.Assert(nestCur >= 0);
            Contracts.Assert(nestCur >= nestDst);
            Contracts.AssertValueOrNull(data);

            NestDst             = nestDst;
            NestSrc             = nestCur;
            Path                = path;
            Data                = data;
            IsDataControlAccess = isDataControlAccess;
            DataControlName     = dataControlName;

            _dataQueryOptions = new Lazy <Dictionary <ExpandPath, ExpandQueryOptions> >();
        }
示例#5
0
        internal static bool TryConvertNodeToDPath(TexlBinding binding, DottedNameNode node, out DPath path)
        {
            Contracts.AssertValue(binding);
            Contracts.AssertValue(node);

            if (node.Left is DottedNameNode && TryConvertNodeToDPath(binding, node.Left as DottedNameNode, out path))
            {
                DName  rightNodeName = node.Right.Name;
                string possibleRename;
                if (binding.TryGetReplacedIdentName(node.Right, out possibleRename))
                {
                    rightNodeName = new DName(possibleRename);
                }

                path = path.Append(rightNodeName);
                return(true);
            }
            else if (node.Left is FirstNameNode firstName)
            {
                if (binding.GetInfo(firstName).Kind == BindKind.LambdaFullRecord)
                {
                    DName rightNodeName = node.Right.Name;
                    if (binding.TryGetReplacedIdentName(node.Right, out string rename))
                    {
                        rightNodeName = new DName(rename);
                    }

                    path = DPath.Root.Append(rightNodeName);
                    return(true);
                }

                // Check if the access was renamed:
                DName  leftNodeName = firstName.Ident.Name;
                string possibleRename;
                if (binding.TryGetReplacedIdentName(firstName.Ident, out possibleRename))
                {
                    leftNodeName = new DName(possibleRename);
                }

                path = DPath.Root.Append(leftNodeName).Append(node.Right.Name);
                return(true);
            }

            path = DPath.Root;
            return(false);
        }
示例#6
0
            public override OperationCapabilityMetadata Parse(JsonElement dataServiceCapabilitiesJsonObject, DType schema)
            {
                Contracts.AssertValid(schema);

                Dictionary <DPath, DelegationCapability> columnRestrictions = new Dictionary <DPath, DelegationCapability>();

                if (!dataServiceCapabilitiesJsonObject.TryGetProperty(CapabilitiesConstants.Sort_Restriction, out var sortRestrictionJsonObject))
                {
                    return(null);
                }

                if (sortRestrictionJsonObject.TryGetProperty(CapabilitiesConstants.Sort_UnsortableProperties, out var unSortablePropertiesJsonArray))
                {
                    foreach (var prop in unSortablePropertiesJsonArray.EnumerateArray())
                    {
                        var columnName = new DName(prop.GetString());
                        var columnPath = DPath.Root.Append(columnName);

                        if (!columnRestrictions.ContainsKey(columnPath))
                        {
                            columnRestrictions.Add(columnPath, new DelegationCapability(DelegationCapability.Sort));
                        }
                    }
                }

                if (sortRestrictionJsonObject.TryGetProperty(CapabilitiesConstants.Sort_AscendingOnlyProperties, out var acendingOnlyPropertiesJsonArray))
                {
                    foreach (var prop in acendingOnlyPropertiesJsonArray.EnumerateArray())
                    {
                        var columnName = new DName(prop.GetString());
                        var columnPath = DPath.Root.Append(columnName);

                        if (!columnRestrictions.ContainsKey(columnPath))
                        {
                            columnRestrictions.Add(columnPath, new DelegationCapability(DelegationCapability.SortAscendingOnly));
                            continue;
                        }

                        var existingRestrictions = columnRestrictions[columnPath].Capabilities;
                        columnRestrictions[columnPath] = new DelegationCapability(existingRestrictions | DelegationCapability.SortAscendingOnly);
                    }
                }

                return(new SortOpMetadata(schema, columnRestrictions));
            }
示例#7
0
        public override bool Lookup(DName name, out NameLookupInfo nameInfo, NameLookupPreferences preferences = NameLookupPreferences.None)
        {
            // Kinds of globals:
            // - global formula
            // - parameters

            string str = name.Value;

            var parameter = _parameters.MaybeGetFieldType(str);

            if (parameter != null)
            {
                var data = new ParameterData {
                    ParameterName = str
                };
                var type = parameter._type;

                nameInfo = new NameLookupInfo(
                    BindKind.PowerFxResolvedObject,
                    type,
                    DPath.Root,
                    0,
                    data
                    );
                return(true);
            }

            if (_parent.Formulas.TryGetValue(str, out var fi))
            {
                var data = fi;
                var type = fi._type._type;

                nameInfo = new NameLookupInfo(
                    BindKind.PowerFxResolvedObject,
                    type,
                    DPath.Root,
                    0,
                    data
                    );
                return(true);
            }

            return(base.Lookup(name, out nameInfo, preferences));
        }
示例#8
0
        public EnumSymbol(DName name, DName invariantName, DType invariantType)
        {
            Contracts.AssertValid(invariantName);
            Contracts.Assert(invariantType.IsEnum);

            Name          = name;
            InvariantName = invariantName;
            EnumType      = invariantType;

            // Initialize the locale-specific enum values, and the loc<->invariant maps.
            _valuesInvariantToLoc         = new Dictionary <string, string>();
            _valuesLocToInvariant         = new Dictionary <string, string>();
            _valuesInvariantToDisplayName = new Dictionary <string, string>();

            foreach (var typedName in EnumType.GetNames(DPath.Root))
            {
                string invName = typedName.Name.Value;

                string locName;
                if (!StringResources.TryGet($"{InvariantName}_{typedName.Name.Value}_Name", out locName))
                {
                    locName = invName;
                }

                Contracts.Assert(DName.IsValidDName(invName));
                _valuesInvariantToLoc[invName] = locName;
                _valuesLocToInvariant[locName] = invName;

                string displayName;
                if (!StringResources.TryGet($"{InvariantName}_{typedName.Name.Value}_DisplayName", out displayName))
                {
                    displayName = locName;
                }

                string custDisplayName;
                string entityNameValue = name.Value;
                if (!EnumStore.TryGetLocalizedEnumValue(entityNameValue, invName, out custDisplayName))
                {
                    custDisplayName = displayName;
                }

                _valuesInvariantToDisplayName[invName] = custDisplayName;
            }
        }
示例#9
0
        internal bool TryGetNamedEnumValueByLocName(DName locName, out DName enumName, out DType enumType, out object value)
        {
            foreach (var info in _enums)
            {
                if (info.TryLookupValueByLocName(locName, out _, out value))
                {
                    enumName = new DName(info.Name);
                    enumType = info.EnumType;
                    return(true);
                }
            }

            // Not found
            enumName = default(DName);
            enumType = null;
            value    = null;

            return(false);
        }
示例#10
0
        private void Build(DName node, Hints hints, CompilerContext ctx)
        {
            var sv = GetVariable(node.Value, node.Location, err: false);

            if (sv.IsEmpty())
            {
                var th = GetTypeHandle(null, node.Value, out var hdl, out var std);

                if (th != CompilerError.None)
                {
                    AddError(CompilerError.UndefinedVariable, node.Location, node.Value);
                }
                else
                {
                    GetMemberNameId(node.Value);
                }

                AddLinePragma(node);
                cw.Type(new TypeHandle(hdl, std));
                return;
            }

            AddLinePragma(node);

            if (!hints.Has(Pop))
            {
                if (NoPush(node, hints))
                {
                    return;
                }

                cw.PushVar(sv);
            }
            else
            {
                if ((sv.Data & VarFlags.Const) == VarFlags.Const)
                {
                    AddError(CompilerError.UnableAssignConstant, node.Location, node.Value);
                }

                cw.PopVar(sv.Address);
            }
        }
示例#11
0
        /// <summary>
        /// Adds suggestions that start with the MatchingString from the given type.
        /// </summary>
        internal static void AddTopLevelSuggestions(IntellisenseData.IntellisenseData intellisenseData, DType type, string prefix = "")
        {
            Contracts.AssertValue(intellisenseData);
            Contracts.Assert(type.IsValid);
            Contracts.Assert(prefix.Length == 0 || (TexlLexer.PunctuatorBang + TexlLexer.PunctuatorDot).IndexOf(prefix[prefix.Length - 1]) >= 0);

            foreach (TypedName tName in type.GetAllNames(DPath.Root))
            {
                if (!intellisenseData.TryAddCustomColumnTypeSuggestions(tName.Type))
                {
                    var    usedName = tName.Name;
                    string maybeDisplayName;
                    if (DType.TryGetDisplayNameForColumn(type, usedName, out maybeDisplayName))
                    {
                        usedName = new DName(maybeDisplayName);
                    }
                    AddSuggestion(intellisenseData, prefix + TexlLexer.EscapeName(usedName.Value), SuggestionKind.Global, SuggestionIconKind.Other, tName.Type, requiresSuggestionEscaping: false);
                }
            }
        }
示例#12
0
        internal static void AddSuggestionsForNamesInType(DType type, IntellisenseData.IntellisenseData data, bool createTableSuggestion)
        {
            Contracts.AssertValid(type);
            Contracts.AssertValue(data);

            foreach (var field in type.GetNames(DPath.Root))
            {
                var    usedName = field.Name;
                string maybeDisplayName;
                if (DType.TryGetDisplayNameForColumn(type, usedName, out maybeDisplayName))
                {
                    usedName = new DName(maybeDisplayName);
                }

                DType suggestionType = field.Type;
                if (createTableSuggestion)
                {
                    suggestionType = DType.CreateTable(new TypedName(type, usedName));
                }

                AddSuggestion(data, usedName.Value, SuggestionKind.Field, SuggestionIconKind.Other, suggestionType, requiresSuggestionEscaping: true);
            }
        }
示例#13
0
        /// <summary>
        /// Enumerates the default enum declarations
        /// </summary>
        /// <returns>
        /// List of enum tuples where the first item in the tuple is the internal identifier, the second item is the
        /// invariant identifier, and the third is the enum's type
        /// </returns>
        internal static IEnumerable <Tuple <DName, DName, DType> > Enums()
        {
            CollectionUtils.EnsureInstanceCreated(ref _enumTypes, () =>
            {
                return(RegenerateEnumTypes());
            });

            foreach (var enumSpec in _enums)
            {
                Contracts.Assert(DName.IsValidDName(enumSpec.Key));

                var name = new DName(enumSpec.Key);
                yield return(new Tuple <DName, DName, DType>(name, name, _enumTypes[enumSpec.Key]));
            }

            foreach (var enumSpec in _customEnumDict.Values)
            {
                Contracts.Assert(DName.IsValidDName(enumSpec.Item1));
                Contracts.Assert(DName.IsValidDName(enumSpec.Item2));

                yield return(new Tuple <DName, DName, DType>(new DName(enumSpec.Item1), new DName(enumSpec.Item2), _enumTypes[enumSpec.Item2]));
            }
        }
示例#14
0
 public Decision(DName decision, int amount)
 {
     this.name   = decision;
     this.amount = amount;
 }
示例#15
0
        public override bool CheckInvocation(TexlBinding binding, TexlNode[] args, DType[] argTypes, IErrorContainer errors, out DType returnType, out Dictionary <TexlNode, DType> nodeToCoercedTypeMap)
        {
            Contracts.AssertValue(args);
            Contracts.AssertValue(argTypes);
            Contracts.Assert(args.Length == argTypes.Length);
            Contracts.AssertValue(errors);
            Contracts.Assert(MinArity <= args.Length && args.Length <= MaxArity);

            bool fArgsValid = base.CheckInvocation(args, argTypes, errors, out returnType, out nodeToCoercedTypeMap);

            Contracts.Assert(returnType.IsTable);

            if (!argTypes[0].IsTable)
            {
                fArgsValid = false;
                errors.EnsureError(DocumentErrorSeverity.Severe, args[0], TexlStrings.ErrNeedTable_Func, Name);
            }
            else
            {
                returnType = argTypes[0];
            }

            // The result type has N fewer columns, as specified by (args[1],args[2],args[3],...)
            int count = args.Length;

            for (var i = 1; i < count; i++)
            {
                TexlNode nameArg     = args[i];
                DType    nameArgType = argTypes[i];

                // Verify we have a string literal for the column name. Accd to spec, we don't support
                // arbitrary expressions that evaluate to string values, because these values contribute to
                // type analysis, so they need to be known upfront (before DropColumns executes).
                StrLitNode nameNode;
                if (nameArgType.Kind != DKind.String || (nameNode = nameArg.AsStrLit()) == null)
                {
                    fArgsValid = false;
                    errors.EnsureError(DocumentErrorSeverity.Severe, nameArg, TexlStrings.ErrExpectedStringLiteralArg_Name, nameArg.ToString());
                    continue;
                }

                // Verify that the name is valid.
                if (!DName.IsValidDName(nameNode.Value))
                {
                    fArgsValid = false;
                    errors.EnsureError(DocumentErrorSeverity.Severe, nameArg, TexlStrings.ErrArgNotAValidIdentifier_Name, nameNode.Value);
                    continue;
                }

                DName columnName = new DName(nameNode.Value);

                // Verify that the name exists.
                DType columnType;
                if (!returnType.TryGetType(columnName, out columnType))
                {
                    fArgsValid = false;
                    returnType.ReportNonExistingName(FieldNameKind.Logical, errors, columnName, nameArg);
                    continue;
                }

                // Drop the specified column from the result type.
                bool fError = false;
                returnType = returnType.Drop(ref fError, DPath.Root, columnName);
                Contracts.Assert(!fError);
            }

            return(fArgsValid);
        }
示例#16
0
        public bool CheckForFullyQualifiedFieldAccess(bool isRHSDelegableTable, BinaryOpNode binaryOpNode, TexlBinding binding, TexlNode node, ref DName columnName, ref FirstNameInfo info)
        {
            Contracts.AssertValue(binaryOpNode);
            Contracts.AssertValue(binding);
            Contracts.AssertValue(node);

            // Check for fully qualified field access
            var firstNameNode  = isRHSDelegableTable ? binaryOpNode.Left?.AsFirstName() : binaryOpNode.Right?.AsFirstName();
            var dottedNameNode = isRHSDelegableTable ? binaryOpNode.Left?.AsDottedName() : binaryOpNode.Right?.AsDottedName();

            if (dottedNameNode != null && dottedNameNode.Left is FirstNameNode possibleScopeAccess && (info = binding.GetInfo(possibleScopeAccess))?.Kind == BindKind.LambdaFullRecord)
            {
                columnName = dottedNameNode.Right.Name;
            }
示例#17
0
 public bool TryLookupEnum(DName name, out NameLookupInfo lookupInfo)
 {
     throw new System.NotImplementedException();
 }
示例#18
0
 public virtual bool LookupGlobalEntity(DName name, out NameLookupInfo lookupInfo)
 {
     lookupInfo = default;
     return(false);
 }
        public SingleColumnTableAccessNode(IRContext irContext, IntermediateNode from, DName field) : base(irContext)
        {
            Contracts.AssertValid(field);
            Contracts.AssertValue(from);

            From  = from;
            Field = field;
        }
示例#20
0
 public bool LookupDataControl(DName name, out NameLookupInfo lookupInfo, out DName dataControlName)
 {
     dataControlName = default;
     lookupInfo      = default;
     return(false);
 }
示例#21
0
        public bool IsValidDottedNameNode(DottedNameNode node, TexlBinding binding, OperationCapabilityMetadata metadata, IOpDelegationStrategy opDelStrategy)
        {
            Contracts.AssertValue(node);
            Contracts.AssertValue(binding);
            Contracts.AssertValueOrNull(opDelStrategy);

            var isRowScoped = binding.IsRowScope(node);

            if (!isRowScoped)
            {
                return(IsValidNode(node, binding));
            }

            bool isRowScopedDelegationExempted;

            if (!IsValidRowScopedDottedNameNode(node, binding, metadata, out isRowScopedDelegationExempted))
            {
                var telemetryMessage = string.Format("Kind:{0}, isRowScoped:{1}",
                                                     node.Kind, isRowScoped);

                SuggestDelegationHintAndAddTelemetryMessage(node, binding, telemetryMessage);
                return(false);
            }

            if (isRowScopedDelegationExempted)
            {
                binding.SetBlockScopedConstantNode(node);
                return(true);
            }

            if (binding.TryGetFullRecordRowScopeAccessInfo(node, out var firstNameInfo))
            {
                // This means that this row scoped field is from some parent scope which is non-delegatable. That should deny delegation at that point.
                // For this scope, this means that value will be provided from some other source.
                // For example, AddColumns(CDS As Left, "Column1", LookUp(CDS1, Left.Name in FirstName))
                // CDS - *[Name:s], CDS1 - *[FirstName:s]
                if (GetCapabilityMetadata(firstNameInfo) == null)
                {
                    return(true);
                }
            }

            if (!binding.GetType(node.Left).HasExpandInfo)
            {
                DPath columnPath;
                if (!BinderUtils.TryConvertNodeToDPath(binding, node, out columnPath) || !metadata.IsDelegationSupportedByColumn(columnPath, _function.FunctionDelegationCapability))
                {
                    var safeColumnName = CharacterUtils.MakeSafeForFormatString(columnPath.ToDottedSyntax());
                    var message        = string.Format(StringResources.Get(TexlStrings.OpNotSupportedByColumnSuggestionMessage_OpNotSupportedByColumn), safeColumnName);
                    SuggestDelegationHintAndAddTelemetryMessage(node, binding, message, TexlStrings.OpNotSupportedByColumnSuggestionMessage_OpNotSupportedByColumn, safeColumnName);
                    TrackingProvider.Instance.SetDelegationTrackerStatus(DelegationStatus.NoDelSupportByColumn, node, binding, _function, DelegationTelemetryInfo.CreateNoDelSupportByColumnTelemetryInfo(columnPath.ToDottedSyntax()));
                    return(false);
                }

                // If there is any operator applied on this node then check if column supports operation.
                return(opDelStrategy?.IsOpSupportedByColumn(metadata, node, columnPath, binding) ?? true);
            }

            // If there is an entity reference then we need to do additional verification.
            IExpandInfo info           = binding.GetType(node.Left).ExpandInfo.VerifyValue();
            var         dataSourceInfo = info.ParentDataSource;

            IDataEntityMetadata entityMetadata;

            if (!dataSourceInfo.DataEntityMetadataProvider.TryGetEntityMetadata(info.Identity, out entityMetadata))
            {
                var telemetryMessage = string.Format("Kind:{0}, isRowScoped:{1}, no metadata found for entity {2}",
                                                     node.Kind, isRowScoped, CharacterUtils.MakeSafeForFormatString(info.Identity));

                SuggestDelegationHintAndAddTelemetryMessage(node, binding, telemetryMessage);
                return(false);
            }

            OperationCapabilityMetadata entityCapabilityMetadata = GetScopedOperationCapabilityMetadata(entityMetadata.DelegationMetadata);
            string maybeLogicalName;
            DName  columnName = node.Right.Name;

            if (entityMetadata.DisplayNameMapping.TryGetFromSecond(node.Right.Name.Value, out maybeLogicalName))
            {
                columnName = new DName(maybeLogicalName);
            }

            var entityColumnPath = DPath.Root.Append(columnName);

            if (!entityCapabilityMetadata.IsDelegationSupportedByColumn(entityColumnPath, _function.FunctionDelegationCapability))
            {
                var safeColumnName = CharacterUtils.MakeSafeForFormatString(columnName.Value);
                var message        = string.Format(StringResources.Get(TexlStrings.OpNotSupportedByColumnSuggestionMessage_OpNotSupportedByColumn), safeColumnName);
                SuggestDelegationHintAndAddTelemetryMessage(node, binding, message, TexlStrings.OpNotSupportedByColumnSuggestionMessage_OpNotSupportedByColumn, safeColumnName);
                TrackingProvider.Instance.SetDelegationTrackerStatus(DelegationStatus.NoDelSupportByColumn, node, binding, _function, DelegationTelemetryInfo.CreateNoDelSupportByColumnTelemetryInfo(columnName));
                return(false);
            }

            // If there is any operator applied on this node then check if column supports operation.
            return(opDelStrategy?.IsOpSupportedByColumn(entityCapabilityMetadata, node, entityColumnPath, binding) ?? true);
        }
 public bool HasTabualarDataSource(DName tabularDataSourceName)
 {
     return(_tabularDataQueryOptionsSet.ContainsKey(tabularDataSourceName));
 }
示例#23
0
            public override void PostVisit(DottedNameNode node)
            {
                Contracts.AssertValue(node);

                DType                  lhsType = _txb.GetType(node.Left);
                DType                  typeRhs = DType.Invalid;
                DName                  nameRhs = node.Right.Name;
                FirstNameInfo          firstNameInfo;
                FirstNameNode          firstNameNode;
                IExternalTableMetadata tableMetadata;
                DType                  nodeType = DType.Unknown;

                if (node.Left.Kind != NodeKind.FirstName &&
                    node.Left.Kind != NodeKind.DottedName)
                {
                    SetDottedNameError(node, TexlStrings.ErrInvalidName);
                    return;
                }

                nameRhs = GetLogicalNodeNameAndUpdateDisplayNames(lhsType, node.Right);

                if (!lhsType.TryGetType(nameRhs, out typeRhs))
                {
                    SetDottedNameError(node, TexlStrings.ErrInvalidName);
                    return;
                }

                // There are two cases:
                // 1. RHS could be an option set.
                // 2. RHS could be a data entity.
                // 3. RHS could be a column name and LHS would be a datasource.
                if (typeRhs.IsOptionSet)
                {
                    nodeType = typeRhs;
                }
                else if (typeRhs.IsExpandEntity)
                {
                    var entityInfo = typeRhs.ExpandInfo;
                    Contracts.AssertValue(entityInfo);

                    string entityPath = string.Empty;
                    if (lhsType.HasExpandInfo)
                    {
                        entityPath = lhsType.ExpandInfo.ExpandPath.ToString();
                    }

                    DType expandedEntityType = GetExpandedEntityType(typeRhs, entityPath);

                    var parentDataSource = entityInfo.ParentDataSource;
                    var metadata         = new DataTableMetadata(parentDataSource.Name, parentDataSource.Name);
                    nodeType = DType.CreateMetadataType(new DataColumnMetadata(typeRhs.ExpandInfo.Name, expandedEntityType, metadata));
                }
                else if ((firstNameNode = node.Left.AsFirstName()) != null && (firstNameInfo = _txb.GetInfo(firstNameNode)) != null)
                {
                    var tabularDataSourceInfo = firstNameInfo.Data as IExternalTabularDataSource;
                    tableMetadata = tabularDataSourceInfo?.TableMetadata;
                    if (tableMetadata == null || !tableMetadata.TryGetColumn(nameRhs.Value, out var columnMetadata) || !IsColumnMultiChoice(columnMetadata))
                    {
                        SetDottedNameError(node, TexlStrings.ErrInvalidName);
                        return;
                    }

                    var metadata = new DataTableMetadata(tabularDataSourceInfo.Name, tableMetadata.DisplayName);
                    nodeType = DType.CreateMetadataType(new DataColumnMetadata(columnMetadata, metadata));
                }
                else
                {
                    SetDottedNameError(node, TexlStrings.ErrInvalidName);
                    return;
                }

                Contracts.AssertValid(nodeType);

                _txb.SetType(node, nodeType);
                _txb.SetInfo(node, new DottedNameInfo(node));
            }
示例#24
0
        public override bool CheckInvocation(TexlBinding binding, TexlNode[] args, DType[] argTypes, IErrorContainer errors, out DType returnType, out Dictionary <TexlNode, DType> nodeToCoercedTypeMap)
        {
            Contracts.AssertValue(args);
            Contracts.AssertAllValues(args);
            Contracts.AssertValue(argTypes);
            Contracts.Assert(args.Length == argTypes.Length);
            Contracts.AssertValue(errors);
            Contracts.Assert(MinArity <= args.Length && args.Length <= MaxArity);

            bool fValid = base.CheckInvocation(args, argTypes, errors, out returnType, out nodeToCoercedTypeMap);

            Contracts.Assert(returnType.IsTable);

            returnType = argTypes[0];

            DType sourceType = argTypes[0];

            for (int i = 1; i < args.Length; i += 2)
            {
                TexlNode   colNameArg     = args[i];
                DType      colNameArgType = argTypes[i];
                StrLitNode nameNode;

                if (colNameArgType.Kind != DKind.String)
                {
                    errors.EnsureError(DocumentErrorSeverity.Severe, colNameArg, TexlStrings.ErrStringExpected);
                    fValid = false;
                }
                else if ((nameNode = colNameArg.AsStrLit()) != null)
                {
                    // Verify that the name is valid.
                    if (DName.IsValidDName(nameNode.Value))
                    {
                        DName columnName = new DName(nameNode.Value);

                        // Verify that the name exists.
                        DType columnType;
                        if (!sourceType.TryGetType(columnName, out columnType))
                        {
                            sourceType.ReportNonExistingName(FieldNameKind.Logical, errors, columnName, args[i]);
                            fValid = false;
                        }
                        else if (!columnType.IsPrimitive || columnType.IsOptionSet)
                        {
                            fValid = false;
                            errors.EnsureError(colNameArg, TexlStrings.ErrSortWrongType);
                        }
                    }
                    else
                    {
                        errors.EnsureError(DocumentErrorSeverity.Severe, nameNode, TexlStrings.ErrArgNotAValidIdentifier_Name, nameNode.Value);
                        fValid = false;
                    }
                }

                int nextArgIdx = i + 1;
                if (nextArgIdx < args.Length && argTypes[nextArgIdx] != DType.String)
                {
                    fValid = false;
                    errors.EnsureError(args[i + 1], TexlStrings.ErrSortIncorrectOrder);
                }
            }

            return(fValid);
        }
示例#25
0
        public override bool CheckInvocation(TexlBinding binding, TexlNode[] args, DType[] argTypes, IErrorContainer errors, out DType returnType, out Dictionary <TexlNode, DType> nodeToCoercedTypeMap)
        {
            Contracts.AssertValue(args);
            Contracts.AssertValue(argTypes);
            Contracts.Assert(args.Length == argTypes.Length);
            Contracts.AssertValue(errors);
            Contracts.Assert(MinArity <= args.Length && args.Length <= MaxArity);

            bool isValidInvocation = base.CheckInvocation(args, argTypes, errors, out returnType, out nodeToCoercedTypeMap);

            Contracts.Assert(returnType.IsTable);

            if (!argTypes[0].IsTable)
            {
                isValidInvocation = false;
                errors.EnsureError(DocumentErrorSeverity.Severe, args[0], TexlStrings.ErrNeedTable_Func, Name);
            }
            else
            {
                returnType = argTypes[0];
            }

            DType colsToKeep = DType.EmptyTable;

            // The result type has N columns, as specified by (args[1],args[2],args[3],...)
            int count = args.Length;

            for (var i = 1; i < count; i++)
            {
                TexlNode nameArg     = args[i];
                DType    nameArgType = argTypes[i];

                // Verify we have a string literal for the column name. Accd to spec, we don't support
                // arbitrary expressions that evaluate to string values, because these values contribute to
                // type analysis, so they need to be known upfront (before ShowColumns executes).
                StrLitNode nameNode;
                if (nameArgType.Kind != DKind.String || (nameNode = nameArg.AsStrLit()) == null)
                {
                    isValidInvocation = false;
                    errors.EnsureError(DocumentErrorSeverity.Severe, nameArg, TexlStrings.ErrExpectedStringLiteralArg_Name, nameArg.ToString());
                    continue;
                }

                // Verify that the name is valid.
                if (!DName.IsValidDName(nameNode.Value))
                {
                    isValidInvocation = false;
                    errors.EnsureError(DocumentErrorSeverity.Severe, nameArg, TexlStrings.ErrArgNotAValidIdentifier_Name, nameNode.Value);
                    continue;
                }

                DName columnName = new DName(nameNode.Value);

                // Verify that the name exists.
                DType columnType;
                if (!returnType.TryGetType(columnName, out columnType))
                {
                    isValidInvocation = false;
                    returnType.ReportNonExistingName(FieldNameKind.Logical, errors, columnName, args[i]);
                    continue;
                }

                // Verify that the name was only specified once.
                DType existingColumnType;
                if (colsToKeep.TryGetType(columnName, out existingColumnType))
                {
                    isValidInvocation = false;
                    errors.EnsureError(DocumentErrorSeverity.Warning, nameArg, TexlStrings.WarnColumnNameSpecifiedMultipleTimes_Name, columnName);
                    continue;
                }

                // Make a note of which columns are being kept.
                Contracts.Assert(columnType.IsValid);
                colsToKeep = colsToKeep.Add(columnName, columnType);
            }

            // Drop everything but the columns that need to be kept.
            returnType = colsToKeep;

            return(isValidInvocation);
        }
示例#26
0
        public override bool CheckInvocation(TexlBinding binding, TexlNode[] args, DType[] argTypes, IErrorContainer errors, out DType returnType, out Dictionary <TexlNode, DType> nodeToCoercedTypeMap)
        {
            Contracts.AssertValue(args);
            Contracts.AssertValue(argTypes);
            Contracts.Assert(args.Length == argTypes.Length);
            Contracts.AssertValue(errors);
            Contracts.Assert(MinArity <= args.Length && args.Length <= MaxArity);

            bool fArgsValid = base.CheckInvocation(args, argTypes, errors, out returnType, out nodeToCoercedTypeMap);

            // The first arg determines the scope type for the lambda params, and the return type.
            DType typeScope;

            fArgsValid &= ScopeInfo.CheckInput(args[0], argTypes[0], errors, out typeScope);
            Contracts.Assert(typeScope.IsRecord);

            // The result type has N additional columns, as specified by (args[1],args[2]), (args[3],args[4]), ... etc.
            returnType = typeScope.ToTable();

            int count = args.Length;

            if ((count & 1) == 0)
            {
                errors.EnsureError(DocumentErrorSeverity.Severe, args[0].Parent.CastList().Parent.CastCall(), TexlStrings.ErrBadArityOdd, count);
            }

            for (var i = 1; i < count; i += 2)
            {
                TexlNode nameArg     = args[i];
                DType    nameArgType = argTypes[i];

                // Verify we have a string literal for the column name. Accd to spec, we don't support
                // arbitrary expressions that evaluate to string values, because these values contribute to
                // type analysis, so they need to be known upfront (before AddColumns executes).
                StrLitNode nameNode;
                if (nameArgType.Kind != DKind.String ||
                    (nameNode = nameArg.AsStrLit()) == null)
                {
                    fArgsValid = false;
                    errors.EnsureError(DocumentErrorSeverity.Severe, nameArg, TexlStrings.ErrExpectedStringLiteralArg_Name, nameArg.ToString());
                    continue;
                }

                // Verify that the name is valid.
                if (!DName.IsValidDName(nameNode.Value))
                {
                    fArgsValid = false;
                    errors.EnsureError(DocumentErrorSeverity.Severe, nameArg, TexlStrings.ErrArgNotAValidIdentifier_Name, nameNode.Value);
                    continue;
                }

                DName  columnName = new DName(nameNode.Value);
                string colName;
                if (DType.TryGetDisplayNameForColumn(typeScope, columnName, out colName))
                {
                    columnName = new DName(colName);
                }

                // Verify that the name doesn't already exist as either a logical or display name
                DType  columnType;
                string unused;
                if (typeScope.TryGetType(columnName, out columnType) || DType.TryGetLogicalNameForColumn(typeScope, columnName, out unused))
                {
                    fArgsValid = false;
                    errors.EnsureError(DocumentErrorSeverity.Moderate, nameArg, TexlStrings.ErrColExists_Name, columnName);
                    continue;
                }

                if (i + 1 >= count)
                {
                    break;
                }

                columnType = argTypes[i + 1];

                // Augment the result type to include the specified column, and verify that it
                // hasn't been specified already within the same invocation.
                bool fError = false;
                returnType = returnType.Add(ref fError, DPath.Root, columnName, columnType);
                if (fError)
                {
                    fArgsValid = false;
                    errors.EnsureError(DocumentErrorSeverity.Moderate, nameArg, TexlStrings.ErrColConflict_Name, columnName);
                    continue;
                }
            }

            return(fArgsValid);
        }
示例#27
0
        public NameLookupInfo(BindKind kind, DType type, DPath path, int upCount, object data = null, DName logicalName = default(DName))
        {
            Contracts.Assert(BindKind._Min <= kind && kind < BindKind._Lim);
            Contracts.Assert(upCount >= 0);
            Contracts.AssertValueOrNull(data);

            Kind        = kind;
            Type        = type;
            Path        = path;
            UpCount     = upCount;
            Data        = data;
            LogicalName = logicalName;
        }
示例#28
0
        public override bool CheckInvocation(TexlBinding binding, TexlNode[] args, DType[] argTypes, IErrorContainer errors, out DType returnType, out Dictionary <TexlNode, DType> nodeToCoercedTypeMap)
        {
            Contracts.AssertValue(args);
            Contracts.AssertAllValues(args);
            Contracts.AssertValue(argTypes);
            Contracts.Assert(args.Length == argTypes.Length);
            Contracts.AssertValue(errors);
            Contracts.Assert(MinArity <= args.Length && args.Length <= MaxArity);

            bool fValid = base.CheckInvocation(args, argTypes, errors, out returnType, out nodeToCoercedTypeMap);

            Contracts.Assert(returnType.IsTable);

            returnType = argTypes[0];
            DType      sourceType  = argTypes[0];
            TexlNode   nameArg     = args[1];
            DType      nameArgType = argTypes[1];
            StrLitNode nameNode    = null;
            DType      columnType  = DType.Invalid;

            if (nameArgType.Kind != DKind.String)
            {
                errors.EnsureError(DocumentErrorSeverity.Severe, nameArg, TexlStrings.ErrStringExpected);
                fValid = false;
            }
            else if ((nameNode = nameArg.AsStrLit()) != null)
            {
                // Verify that the name is valid.
                if (DName.IsValidDName(nameNode.Value))
                {
                    DName columnName = new DName(nameNode.Value);

                    // Verify that the name exists.
                    if (!sourceType.TryGetType(columnName, out columnType))
                    {
                        sourceType.ReportNonExistingName(FieldNameKind.Logical, errors, columnName, nameNode);
                        fValid = false;
                    }
                    else if (!columnType.IsPrimitive)
                    {
                        fValid = false;
                        errors.EnsureError(nameArg, TexlStrings.ErrSortWrongType);
                    }
                }
                else
                {
                    errors.EnsureError(DocumentErrorSeverity.Severe, nameNode, TexlStrings.ErrArgNotAValidIdentifier_Name, nameNode.Value);
                    fValid = false;
                }
            }

            TexlNode valuesArg = args[2];
            IEnumerable <TypedName> columns;

            if ((columns = argTypes[2].GetNames(DPath.Root)).Count() != 1)
            {
                errors.EnsureError(DocumentErrorSeverity.Severe, valuesArg, TexlStrings.ErrInvalidSchemaNeedCol);
                return(false);
            }

            TypedName column = columns.Single();

            if (nameNode != null && columnType.IsValid && !columnType.Accepts(column.Type))
            {
                errors.EnsureError(DocumentErrorSeverity.Severe, valuesArg, TexlStrings.ErrTypeError_Arg_Expected_Found, nameNode.Value,
                                   columnType.GetKindString(), column.Type.GetKindString());
                fValid = false;
            }

            return(fValid);
        }
示例#29
0
            /// <summary>
            /// Adds suggestions as appropriate to the internal Suggestions and SubstringSuggestions lists of intellisenseData.
            /// Returns true if intellisenseData is handled and no more suggestions are to be found and false otherwise.
            /// </summary>
            public bool Run(IntellisenseData.IntellisenseData intellisenseData)
            {
                Contracts.AssertValue(intellisenseData);

                if (!TryGetRecordNodeWithinACallNode(intellisenseData.CurNode, out RecordNode recordNode, out CallNode callNode))
                {
                    return(false);
                }

                // For the special case of an identifier of a record which is an argument of a function, we can
                // utilize the data provided to suggest relevant column names
                int cursorPos = intellisenseData.CursorPos;

                bool suggestionsAdded = false;

                Contracts.AssertValue(recordNode);
                Contracts.AssertValue(callNode);

                Identifier columnName = GetRecordIdentifierForCursorPosition(cursorPos, recordNode, intellisenseData.Script);

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

                if (columnName.Token.Span.Min <= cursorPos)
                {
                    var tokenSpan         = columnName.Token.Span;
                    int replacementLength = tokenSpan.Min == cursorPos ? 0 : tokenSpan.Lim - tokenSpan.Min;
                    intellisenseData.SetMatchArea(tokenSpan.Min, cursorPos, replacementLength);
                }

                CallInfo info = intellisenseData.Binding.GetInfo(callNode);
                var      func = info.Function;

                if (func == null || !intellisenseData.IsFunctionElligibleForRecordSuggestions(func))
                {
                    return(false);
                }

                // Adding suggestions for callNode arguments which reference a collection's columns
                if (func.CanSuggestInputColumns)
                {
                    DType aggregateType = GetAggregateType(func, callNode, intellisenseData);
                    if (aggregateType.HasErrors || !aggregateType.IsAggregate)
                    {
                        return(false);
                    }

                    if (aggregateType.ContainsDataEntityType(DPath.Root))
                    {
                        bool error = false;
                        aggregateType = aggregateType.DropAllOfTableRelationships(ref error, DPath.Root);
                        if (error)
                        {
                            return(false);
                        }
                    }

                    foreach (TypedName tName in aggregateType.GetNames(DPath.Root))
                    {
                        var    usedName = tName.Name;
                        string maybeDisplayName;
                        if (DType.TryGetDisplayNameForColumn(aggregateType, usedName, out maybeDisplayName))
                        {
                            usedName = new DName(maybeDisplayName);
                        }

                        string suggestion = TexlLexer.EscapeName(usedName.Value) + (IntellisenseHelper.IsPunctuatorColonNextToCursor(cursorPos, intellisenseData.Script) ? "" : TexlLexer.PunctuatorColon);
                        suggestionsAdded |= IntellisenseHelper.AddSuggestion(intellisenseData, suggestion, SuggestionKind.Field, SuggestionIconKind.Other, DType.String, requiresSuggestionEscaping: false);
                    }

                    return(suggestionsAdded && columnName != null);
                }

                return(intellisenseData.TryAddFunctionRecordSuggestions(func, callNode, columnName));
            }