/// <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)); }
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; }
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); }
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> >(); }
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); }
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)); }
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)); }
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; } }
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); }
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); } }
/// <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); } } }
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); } }
/// <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])); } }
public Decision(DName decision, int amount) { this.name = decision; this.amount = amount; }
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); }
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; }
public bool TryLookupEnum(DName name, out NameLookupInfo lookupInfo) { throw new System.NotImplementedException(); }
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; }
public bool LookupDataControl(DName name, out NameLookupInfo lookupInfo, out DName dataControlName) { dataControlName = default; lookupInfo = default; return(false); }
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)); }
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)); }
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); }
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); }
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); }
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; }
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); }
/// <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)); }