public override void Visit(FirstNameNode node) { if (_txb.EntityScope.TryGetDataSource(node, out var info) && info.Kind == DataSourceKind.CdsNative) { cdsDataSourceInfo = info as IExternalCdsDataSource; } }
// Create a qualified name (global/alias/enum/resource), e.g. "screen1.group25.slider2", or "Color". // Can also be used to create fields of ThisItem (with an appropriate upCount). public static FirstNameInfo Create(FirstNameNode node, NameLookupInfo lookupInfo) { Contracts.AssertValue(node); Contracts.Assert(lookupInfo.Kind != BindKind.LambdaField && lookupInfo.Kind != BindKind.LambdaFullRecord); Contracts.Assert(lookupInfo.UpCount >= 0); Contracts.Assert(lookupInfo.Path.IsValid); return(new FirstNameInfo(lookupInfo.Kind, node, -lookupInfo.UpCount, 0, lookupInfo.Path, lookupInfo.Data, default, false));
private bool TryGetEntityInfo(FirstNameNode firstName, TexlBinding binding, out IExpandInfo entityInfo) { Contracts.AssertValueOrNull(firstName); Contracts.AssertValue(binding); entityInfo = null; if (firstName == null || !binding.GetType(firstName).IsTable) { return(false); } return(binding.TryGetEntityInfo(firstName, out entityInfo)); }
// Verifies if provided column node supports delegation. protected bool IsDelegatableColumnNode(FirstNameNode node, TexlBinding binding, IOpDelegationStrategy opDelStrategy, DelegationCapability capability) { Contracts.AssertValue(node); Contracts.AssertValue(binding); Contracts.AssertValueOrNull(opDelStrategy); Contracts.Assert(binding.IsRowScope(node)); FirstNameInfo firstNameInfo = binding.GetInfo(node.AsFirstName()); if (firstNameInfo == null) { return(false); } IDelegationMetadata metadata = GetCapabilityMetadata(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, "Column1", LookUp(CDS1, Name in FirstName)) // CDS - *[Name:s], CDS1 - *[FirstName:s] if (metadata == null) { return(true); } var columnName = firstNameInfo.Name; Contracts.AssertValid(columnName); var columnPath = DPath.Root.Append(columnName); if (!metadata.FilterDelegationMetadata.IsDelegationSupportedByColumn(columnPath, capability)) { 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(firstNameInfo)); return(false); } // If there is any operator applied on this node then check if column supports operation. if (opDelStrategy != null && !opDelStrategy.IsOpSupportedByColumn(metadata.FilterDelegationMetadata, node.AsFirstName(), columnPath, binding)) { return(false); } return(true); }
public override void Visit(FirstNameNode node) { FirstNameInfo info = _binding.GetInfo(node); var name = node.Ident.Name.Value; // Only include dependencies from the incoming context (Fields) // defined at the top level (NestDst==1) if ((info.NestDst == 1 && info.Kind == BindKind.LambdaField) || (info.Kind == BindKind.ScopeVariable) || (info.Kind == BindKind.PowerFxResolvedObject)) { _vars.Add(name); } base.Visit(node); }
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> >(); }
public override LazyList <string> Visit(FirstNameNode node, Precedence parentPrecedence) { Contracts.AssertValue(node); if (node.Ident.AtToken == null) { return(LazyList <string> .Of(node.Ident.Token.ToString())); } else { return(LazyList <string> .Of( TexlLexer.PunctuatorBracketOpen, TexlLexer.PunctuatorAt, node.Ident.Token.ToString(), TexlLexer.PunctuatorBracketClose)); } }
public override LazyList <string> Visit(FirstNameNode node, Precedence parentPrecedence) { Contracts.AssertValue(node); var info = _binding?.GetInfo(node); if (info != null && info.Kind != BindKind.Unknown) { return(LazyList <string> .Of($"#${Enum.GetName(typeof(BindKind), info.Kind)}$#")); } if (node.Ident.AtToken == null) { return(LazyList <string> .Of("#$firstname$#")); } else { return(LazyList <string> .Of("#$disambiguation$#")); } }
private static bool TryGetLocalScopeInfo(TexlNode node, TexlBinding binding, out ScopedNameLookupInfo info) { Contracts.AssertValue(node); Contracts.AssertValue(binding); if (node.Kind == NodeKind.FirstName) { FirstNameNode curNode = node.CastFirstName(); var firstNameInfo = binding.GetInfo(curNode); if (firstNameInfo.Kind == BindKind.ScopeArgument) { info = (ScopedNameLookupInfo)firstNameInfo.Data; return(true); } } info = new ScopedNameLookupInfo(); return(false); }
public override bool IsRowScopedServerDelegatable(CallNode callNode, TexlBinding binding, OperationCapabilityMetadata metadata) { Contracts.AssertValue(callNode); Contracts.AssertValue(binding); Contracts.AssertValue(metadata); if (binding.ErrorContainer.HasErrors(callNode)) { return(false); } if (!CheckArgsCount(callNode, binding)) { return(false); } TexlNode[] args = callNode.Args.Children.VerifyValue(); var opStrategy = GetOpDelegationStrategy(BinaryOp.Equal, null); if (binding.IsFullRecordRowScopeAccess(args[0])) { return(GetDottedNameNodeDelegationStrategy().IsValidDottedNameNode(args[0] as DottedNameNode, binding, metadata, opStrategy)); } FirstNameNode node = args[0] as FirstNameNode; if (node == null) { var message = string.Format("Arg1 is not a firstname node, instead it is {0}", args[0].Kind); AddSuggestionMessageToTelemetry(message, args[0], binding); return(false); } if (!binding.IsRowScope(node)) { return(false); } var firstNameNodeValidationStrategy = GetFirstNameNodeDelegationStrategy(); return(firstNameNodeValidationStrategy.IsValidFirstNameNode(node, binding, opStrategy)); }
// Parses the RHS of a scope field. E.g., [@bar] in "foo[@bar]" private DottedNameNode ParseScopeField(FirstNameNode lhs) { Contracts.AssertValue(lhs); Contracts.Assert(_curs.TidCur == TokKind.BracketOpen); Contracts.Assert(_curs.TidPeek() == TokKind.At); Token bracketOpen = _curs.TokCur; // Parse the rhs of the dotted name FirstNameNode rhs = ParseBracketIdentifierAsFirstName(); // Form the dotted name return(new DottedNameNode( ref _idNext, bracketOpen, new SourceList(new NodeSource(lhs), new NodeSource(rhs)), lhs, rhs.Ident, rhs)); }
private bool TryGetDsInfo(FirstNameNode firstName, TexlBinding binding, out IExternalDataSource dsInfo) { Contracts.AssertValueOrNull(firstName); Contracts.AssertValue(binding); dsInfo = null; if (firstName == null || !binding.GetType(firstName).IsTable) { return(false); } var firstNameInfo = binding.GetInfo(firstName); if (firstNameInfo == null || firstNameInfo.Kind != BindKind.Data) { return(false); } return(binding.EntityScope != null && binding.EntityScope.TryGetEntity(firstNameInfo.Name, out dsInfo)); }
public bool IsValidFirstNameNode(FirstNameNode node, TexlBinding binding, IOpDelegationStrategy opDelStrategy) { Contracts.AssertValue(node); Contracts.AssertValue(binding); Contracts.AssertValueOrNull(opDelStrategy); var isRowScoped = binding.IsRowScope(node); var isValid = IsValidNode(node, binding); if (isValid && !isRowScoped) { return(true); } // If invalid node then return immediately. if (!isValid) { return(false); } return(IsDelegatableColumnNode(node, binding, opDelStrategy, _function.FunctionDelegationCapability)); }
private bool TryGetValidSortOrderNode(FirstNameNode node, TexlBinding binding, out string sortOrder) { Contracts.AssertValue(node); Contracts.AssertValue(binding); sortOrder = ""; var info = binding.GetInfo(node).VerifyValue(); if (info.Kind != BindKind.Enum) { return(false); } string order = info.Data as string; if (order == null) { return(false); } return(IsValidOrderString(order, out sortOrder)); }
private bool VerifyFirstNameNodeIsValidSortOrderEnum(FirstNameNode node, TexlBinding binding) { Contracts.AssertValue(node); Contracts.AssertValue(binding); var firstNameInfo = binding.GetInfo(node); if (firstNameInfo == null || firstNameInfo.Kind != BindKind.Enum) { return(false); } if (!binding.NameResolver.TryLookupEnum(new DName(LanguageConstants.SortOrderEnumStringInvariant), out var lookupInfo)) { return(false); } DType type = binding.GetType(node); return(type == lookupInfo.Type); }
private static bool TryGetEnumInfo(IntellisenseData.IntellisenseData data, TexlNode node, TexlBinding binding, out EnumSymbol enumSymbol) { Contracts.AssertValue(node); Contracts.AssertValue(binding); FirstNameNode curNode = node.AsFirstName(); if (curNode == null) { enumSymbol = null; return(false); } FirstNameInfo firstNameInfo = binding.GetInfo(curNode).VerifyValue(); if (firstNameInfo.Kind != BindKind.Enum) { enumSymbol = null; return(false); } return(data.TryGetEnumSymbol(firstNameInfo.Name, binding, out enumSymbol)); }
private static bool TryGetNamespaceFunctions(TexlNode node, TexlBinding binding, out IEnumerable <TexlFunction> functions) { Contracts.AssertValue(node); Contracts.AssertValue(binding); FirstNameNode curNode = node.AsFirstName(); if (curNode == null) { functions = EmptyEnumerator <TexlFunction> .Instance; return(false); } FirstNameInfo firstNameInfo = binding.GetInfo(curNode).VerifyValue(); Contracts.AssertValid(firstNameInfo.Name); DPath namespacePath = new DPath().Append(firstNameInfo.Name); functions = binding.NameResolver.LookupFunctionsInNamespace(namespacePath); return(functions.Any()); }
internal override bool TryAddSuggestionsForNodeKind(IntellisenseData.IntellisenseData intellisenseData) { Contracts.AssertValue(intellisenseData); TexlNode curNode = intellisenseData.CurNode; int cursorPos = intellisenseData.CursorPos; FirstNameNode firstNameNode = curNode.CastFirstName(); Identifier ident = firstNameNode.Ident; int min = ident.Token.Span.Min; IdentToken tok = ident.Token; if (cursorPos < min) { // Cursor is before the beginning of the identifier or of the global token if present. // Suggest possibilities that can result in a value. IntellisenseHelper.AddSuggestionsForValuePossibilities(intellisenseData, curNode); intellisenseData.AddAdditionalSuggestionsForKeywordSymbols(curNode); } else if (cursorPos <= tok.Span.Lim) { // Cursor is part of the identifier or global token if present. // Get the matching string as a substring from the script so that the whitespace is preserved. IEnumerable <string> possibleFirstNames = intellisenseData.Binding.GetFirstNames().Select(firstNameInfo => firstNameInfo.Name.Value) .Union(intellisenseData.Binding.GetGlobalNames().Select(firstNameInfo => firstNameInfo.Name.Value)) .Union(intellisenseData.Binding.GetAliasNames().Select(firstNameInfo => firstNameInfo.Name.Value)) .Union(intellisenseData.SuggestableFirstNames); int replacementLength = IntellisenseHelper.GetReplacementLength(intellisenseData, tok.Span.Min, tok.Span.Lim, possibleFirstNames); intellisenseData.SetMatchArea(tok.Span.Min, cursorPos, replacementLength); intellisenseData.BoundTo = intellisenseData.Binding.ErrorContainer.HasErrors(firstNameNode) ? string.Empty : ident.Name; if (ident.AtToken != null || tok.Kind == TokKind.At) { // Suggest globals if cursor is after '@'. AddSuggestionsForScopedGlobals(intellisenseData); } else if (tok.HasDelimiters && cursorPos > tok.Span.Min) { // Suggest top level fields and globals if cursor is after a opening square bracket. IntellisenseHelper.AddSuggestionsForRuleScope(intellisenseData); IntellisenseHelper.AddSuggestionsForTopLevel(intellisenseData, curNode); IntellisenseHelper.AddSuggestionsForGlobals(intellisenseData); intellisenseData.AddAdditionalSuggestionsForLocalSymbols(); } else { // Suggest value posssibilities otherwise. IntellisenseHelper.AddSuggestionsForValuePossibilities(intellisenseData, curNode); } intellisenseData.AddAdditionalSuggestionsForKeywordSymbols(curNode); } else if (IsBracketOpen(tok.Span.Lim, cursorPos, intellisenseData.Script)) { AddSuggestionsForScopeFields(intellisenseData, intellisenseData.Binding.GetType(firstNameNode)); } else if (IntellisenseHelper.CanSuggestAfterValue(cursorPos, intellisenseData.Script)) { // Verify that cursor is after a space after the identifier. // Suggest binary keywords. IntellisenseHelper.AddSuggestionsForAfterValue(intellisenseData, intellisenseData.Binding.GetType(firstNameNode)); } return(true); }
public abstract Result Visit(FirstNameNode node, Context context);
// Parse a record expression of the form: {id:expr, id:expr, ...} // or of the form ident@{id:expr, id:expr} private RecordNode ParseRecordExpr(ITexlSource sourceRestrictionTrivia, Identifier sourceRestriction = null) { Contracts.Assert(_curs.TidCur == TokKind.CurlyOpen || _curs.TidCur == TokKind.At); Contracts.AssertValueOrNull(sourceRestriction); Token curlyClose; var commas = new List <Token>(); var colons = new List <Token>(); var ids = new List <Identifier>(); var exprs = new List <TexlNode>(); var sourceList = new List <ITexlSource>(); TexlNode sourceRestrictionNode = null; Token primaryToken = _curs.TokMove(); if (primaryToken.Kind == TokKind.At) { Contracts.AssertValue(sourceRestriction); sourceList.Add(sourceRestrictionTrivia); sourceList.Add(new TokenSource(primaryToken)); sourceList.Add(ParseTrivia()); primaryToken = sourceRestriction.Token; sourceRestrictionNode = new FirstNameNode(ref _idNext, sourceRestriction.Token, sourceRestriction); if (_curs.TidCur != TokKind.CurlyOpen) { ErrorTid(_curs.TokCur, TokKind.CurlyOpen); curlyClose = TokEat(TokKind.CurlyClose); return(new RecordNode( ref _idNext, sourceRestriction.Token, new SourceList( new SpreadSource(sourceList), curlyClose != null ? (ITexlSource) new TokenSource(curlyClose) : new SpreadSource()), ids.ToArray(), exprs.ToArray(), null, null, curlyClose, sourceRestrictionNode)); } sourceList.Add(new TokenSource(_curs.TokMove())); sourceList.Add(ParseTrivia()); } else { sourceList.Add(new TokenSource(primaryToken)); sourceList.Add(ParseTrivia()); } while (_curs.TidCur != TokKind.CurlyClose) { // id Identifier ident = ParseIdentifier(); sourceList.Add(new IdentifierSource(ident)); sourceList.Add(ParseTrivia()); // : if (_curs.TidCur != TokKind.Colon) { ErrorTid(_curs.TokCur, TokKind.Colon); var errorToken = _curs.TokMove(); TexlNode errorExp = CreateError(errorToken, TexlStrings.ErrColonExpected); sourceList.Add(new TokenSource(errorToken)); sourceList.Add(ParseTrivia()); ids.Add(ident); exprs.Add(errorExp); break; } var colon = _curs.TokMove(); colons.Add(colon); sourceList.Add(new TokenSource(colon)); sourceList.Add(ParseTrivia()); // expr // SingleExpr here means we don't want chains, but individual expressions. TexlNode expr = ParseExpr(Precedence.SingleExpr); ids.Add(ident); exprs.Add(expr); sourceList.Add(new NodeSource(expr)); sourceList.Add(ParseTrivia()); // , if (_curs.TidCur != TokKind.Comma) { break; } var comma = _curs.TokMove(); commas.Add(comma); sourceList.Add(new TokenSource(comma)); sourceList.Add(ParseTrivia()); if (_curs.TidCur == TokKind.CurlyClose) { TexlNode errorExp = CreateError(comma, TexlStrings.ErrColonExpected); exprs.Add(errorExp); ids.Add(ParseIdentifier()); } } Contracts.Assert(ids.Count == exprs.Count); Token[] commaArray = (commas != null) ? commas.ToArray() : null; Token[] colonArray = (colons != null) ? colons.ToArray() : null; curlyClose = TokEat(TokKind.CurlyClose); if (curlyClose != null) { sourceList.Add(new TokenSource(curlyClose)); } return(new RecordNode( ref _idNext, primaryToken, new SourceList(sourceList), ids.ToArray(), exprs.ToArray(), commaArray, colonArray, curlyClose, sourceRestrictionNode)); }
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); }
public override Result Visit(FirstNameNode node, Context context) { return(Default); }
public abstract void Visit(FirstNameNode node);
public override void Visit(FirstNameNode node) { }
public override void Visit(FirstNameNode node) { SetCurrentNodeAsResult(node); }