/// <summary> /// Adds suggestions for type scoped at current cursor position. /// </summary> public static void AddTopLevelSuggestionsForCursorType(IntellisenseData.IntellisenseData intellisenseData, CallNode callNode, int argPosition) { Contracts.AssertValue(intellisenseData); Contracts.AssertValue(callNode); Contracts.Assert(argPosition >= 0); CallInfo info = intellisenseData.Binding.GetInfo(callNode); Contracts.AssertValue(info); DType type = info.CursorType; // Suggestions are added for the error nodes in the next step. if (info.Function != null && argPosition <= info.Function.MaxArity && info.Function.IsLambdaParam(argPosition) && !info.Function.HasSuggestionsForParam(argPosition) && type.IsValid) { if (info.Function.IsLambdaParam(argPosition) && type.ContainsDataEntityType(DPath.Root)) { bool error = false; type = type.DropAllOfTableRelationships(ref error, DPath.Root); if (error) { return; } } if (info.ScopeIdentifier != default) { AddSuggestion(intellisenseData, info.ScopeIdentifier, SuggestionKind.Global, SuggestionIconKind.Other, type, requiresSuggestionEscaping: false); } if (!info.RequiresScopeIdentifier) { AddTopLevelSuggestions(intellisenseData, type); } } }
/// <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)); }