/// <summary> /// Based on our current token, determine how much of it should be replaced /// </summary> /// <param name="intellisenseData"></param> /// <param name="tokenStart"></param> /// <param name="tokenEnd"></param> /// <param name="validNames"></param> /// <returns></returns> internal static int GetReplacementLength(IntellisenseData.IntellisenseData intellisenseData, int tokenStart, int tokenEnd, IEnumerable <string> validNames) { Contracts.AssertValue(intellisenseData); Contracts.Assert(tokenStart <= intellisenseData.CursorPos); Contracts.Assert(intellisenseData.CursorPos <= tokenEnd); Contracts.Assert(tokenEnd <= intellisenseData.Script.Length); Contracts.AssertAllNonEmpty(validNames); int cursorPos = intellisenseData.CursorPos; // If the cursor is at the start of a token, then do not replace anything if (tokenStart == intellisenseData.CursorPos) { return(0); } string forwardOverwrittenText = intellisenseData.Script.Substring(cursorPos, tokenEnd - cursorPos); foreach (var validName in validNames) { Contracts.AssertNonEmpty(validName); if (validName == forwardOverwrittenText) { return(cursorPos - tokenStart); // If the remaining text of the token is a valid name, we shouldn't overwrite it } } return(tokenEnd - tokenStart); }
private IIntellisenseResult Finalize(IIntellisenseContext context, IntellisenseData.IntellisenseData intellisenseData) { Contracts.AssertValue(context); Contracts.AssertValue(intellisenseData); DType expectedType = intellisenseData.ExpectedType; TypeMatchPriority(expectedType, intellisenseData.Suggestions); TypeMatchPriority(expectedType, intellisenseData.SubstringSuggestions); intellisenseData.Suggestions.Sort(); intellisenseData.SubstringSuggestions.Sort(); List <IntellisenseSuggestion> resultSuggestions = intellisenseData.Suggestions.Distinct().ToList(); IEnumerable <IntellisenseSuggestion> resultSubstringSuggestions = intellisenseData.SubstringSuggestions.Distinct(); resultSuggestions.AddRange(resultSubstringSuggestions); TypeFilter(expectedType, intellisenseData.MatchingStr, ref resultSuggestions); foreach (var handler in intellisenseData.CleanupHandlers) { handler.Run(context, intellisenseData, resultSuggestions); } return(new IntellisenseResult(intellisenseData, resultSuggestions)); }
/// <summary> /// Adds suggestions for an enum, with an optional prefix. /// </summary> /// <param name="intellisenseData"></param> /// <param name="enumInfo"></param> /// <param name="prefix"></param> internal static void AddSuggestionsForEnum(IntellisenseData.IntellisenseData intellisenseData, EnumSymbol enumInfo, string prefix = "") { Contracts.AssertValue(intellisenseData); Contracts.AssertValue(enumInfo); Contracts.AssertValue(prefix); bool anyCollisionExists = false; var locNameTypePairs = new List <Tuple <String, DType> >(); // We do not need to get the localized names since GetNames will only return invariant. // Instead, we use the invariant names later with the enumInfo to retrieve the localized name. foreach (var typedName in enumInfo.EnumType.GetNames(DPath.Root)) { string locName; enumInfo.TryGetLocValueName(typedName.Name.Value, out locName).Verify(); string escapedLocName = TexlLexer.EscapeName(locName); var collisionExists = intellisenseData.DoesNameCollide(locName); if (collisionExists) { string candidate = prefix + escapedLocName; bool canAddSuggestion = _addSuggestionDryRunHelper.AddSuggestion(intellisenseData, candidate, SuggestionKind.Global, SuggestionIconKind.Other, typedName.Type, false); anyCollisionExists = anyCollisionExists || canAddSuggestion; } locNameTypePairs.Add(new Tuple <String, DType>(escapedLocName, typedName.Type)); } foreach (var locNameTypePair in locNameTypePairs) { string suggestion = anyCollisionExists || !intellisenseData.SuggestUnqualifiedEnums ? prefix + locNameTypePair.Item1 : locNameTypePair.Item1; AddSuggestion(intellisenseData, suggestion, SuggestionKind.Global, SuggestionIconKind.Other, locNameTypePair.Item2, false); } }
public static void AddSuggestionsForUnaryOperatorKeyWords(IntellisenseData.IntellisenseData intellisenseData) { Contracts.AssertValue(intellisenseData); // TASK: 76039: Intellisense: Update intellisense to filter suggestions based on the expected type of the text being typed in UI IntellisenseHelper.AddSuggestionsForMatches(intellisenseData, TexlLexer.LocalizedInstance.GetUnaryOperatorKeywords(), SuggestionKind.KeyWord, SuggestionIconKind.Other, requiresSuggestionEscaping: false); }
/// <summary> /// Adds suggestions that start with the matchingString from the result from the types in scope. /// </summary> internal static bool AddSuggestionsForTopLevel(IntellisenseData.IntellisenseData intellisenseData, TexlNode node) { Contracts.AssertValue(intellisenseData); Contracts.AssertValue(node); return(AddTopLevelSuggestionsForGivenNode(intellisenseData, node, node)); }
internal static DType GetEnumType(IntellisenseData.IntellisenseData intellisenseData, TexlNode node) { Contracts.AssertValue(intellisenseData); Contracts.AssertValue(node); DottedNameNode dottedNode; FirstNameNode firstNameNode; if ((dottedNode = node.AsDottedName()) != null) { return(intellisenseData.Binding.GetType(dottedNode.Left)); } if ((firstNameNode = node.AsFirstName()) != null) { FirstNameInfo firstNameInfo = intellisenseData.Binding.GetInfo(firstNameNode).VerifyValue(); DPath parent = firstNameInfo.Path.Parent; if (!parent.Name.IsValid) { return(DType.Unknown); } if (intellisenseData.TryGetEnumSymbol(parent.Name, intellisenseData.Binding, out EnumSymbol enumSymbol)) { return(enumSymbol.EnumType); } } return(DType.Unknown); }
/// <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); Contracts.AssertValue(intellisenseData.CurNode); if (intellisenseData.CurNode.Kind != NodeKind.StrLit && intellisenseData.CurNode.Kind != NodeKind.NumLit) { return(false); } TexlNode curNode = intellisenseData.CurNode; int cursorPos = intellisenseData.CursorPos; var tokenSpan = curNode.Token.Span; // Should not suggest anything if the cursor is before the string/number. if (cursorPos > tokenSpan.Lim && IntellisenseHelper.CanSuggestAfterValue(cursorPos, intellisenseData.Script)) { // Cursor is after the current node's token. // Suggest binary kewords. DType operandType = curNode.Kind == NodeKind.StrLit ? DType.String : DType.Number; IntellisenseHelper.AddSuggestionsForAfterValue(intellisenseData, operandType); } else if (cursorPos > tokenSpan.Min) { // Cursor is in the middle of the token, Suggest Globals matching the input string or number. int replacementLength = tokenSpan.Lim - tokenSpan.Min; intellisenseData.SetMatchArea(tokenSpan.Min, cursorPos, replacementLength); IntellisenseHelper.AddSuggestionsForGlobals(intellisenseData); } return(true); }
internal override bool TryAddSuggestionsForNodeKind(IntellisenseData.IntellisenseData intellisenseData) { Contracts.AssertValue(intellisenseData); TexlNode curNode = intellisenseData.CurNode; int cursorPos = intellisenseData.CursorPos; BoolLitNode boolNode = curNode.CastBoolLit(); var tokenSpan = curNode.Token.Span; if (cursorPos < tokenSpan.Min) { // Cursor is before the token start. IntellisenseHelper.AddSuggestionsForValuePossibilities(intellisenseData, curNode); } else if (cursorPos <= tokenSpan.Lim) { // Cursor is in the middle of the token. int replacementLength = tokenSpan.Min == cursorPos ? 0 : tokenSpan.Lim - tokenSpan.Min; intellisenseData.SetMatchArea(tokenSpan.Min, cursorPos, replacementLength); intellisenseData.BoundTo = boolNode.Value ? TexlLexer.KeywordTrue : TexlLexer.KeywordFalse; IntellisenseHelper.AddSuggestionsForValuePossibilities(intellisenseData, curNode); } else if (IntellisenseHelper.CanSuggestAfterValue(cursorPos, intellisenseData.Script)) { // Verify that cursor is after a space after the current node's token. // Suggest binary keywords. IntellisenseHelper.AddSuggestionsForAfterValue(intellisenseData, DType.Boolean); } return(true); }
private void AddSuggestionsForLeftNodeScope(IntellisenseData.IntellisenseData intellisenseData, TexlNode leftNode, bool isOneColumnTable, DType leftType) { Contracts.AssertValue(intellisenseData); Contracts.AssertValue(leftNode); Contracts.AssertValue(leftType); if (!intellisenseData.TryAddSuggestionsForLeftNodeScope(leftNode)) { if (TryGetEnumInfo(intellisenseData, leftNode, intellisenseData.Binding, out EnumSymbol enumInfo)) { IntellisenseHelper.AddSuggestionsForEnum(intellisenseData, enumInfo); } else if (TryGetNamespaceFunctions(leftNode, intellisenseData.Binding, out IEnumerable <TexlFunction> namespaceFunctions)) { AddSuggestionsForNamespace(intellisenseData, namespaceFunctions); } else if (TryGetLocalScopeInfo(leftNode, intellisenseData.Binding, out ScopedNameLookupInfo info)) { IntellisenseHelper.AddTopLevelSuggestions(intellisenseData, info.Type); } else if (!isOneColumnTable) { AddSuggestionsForDottedName(intellisenseData, leftType); } } intellisenseData.OnAddedSuggestionsForLeftNodeScope(leftNode); }
internal override bool TryAddSuggestionsForNodeKind(IntellisenseData.IntellisenseData intellisenseData) { Contracts.AssertValue(intellisenseData); TexlNode curNode = intellisenseData.CurNode; int cursorPos = intellisenseData.CursorPos; // Cursor is in the operation token or before. // Suggest all value possibilities. UnaryOpNode unaryOpNode = curNode.CastUnaryOp(); var tokenSpan = unaryOpNode.Token.Span; if (cursorPos < tokenSpan.Min) { return(false); } Contracts.Assert(cursorPos >= tokenSpan.Min || cursorPos <= tokenSpan.Lim); string keyword = TexlParser.GetTokString(unaryOpNode.Token.Kind); Contracts.Assert(intellisenseData.MatchingLength <= keyword.Length); var replacementLength = tokenSpan.Min == cursorPos ? 0 : tokenSpan.Lim - tokenSpan.Min; intellisenseData.SetMatchArea(tokenSpan.Min, cursorPos, replacementLength); intellisenseData.BoundTo = intellisenseData.MatchingLength == 0 ? string.Empty : keyword; IntellisenseHelper.AddSuggestionsForValuePossibilities(intellisenseData, curNode); return(true); }
// Suggest the Globals that can appear in the context of '[@____]' // Suggesting controls, datasources, appVariables, and enums. private static void AddSuggestionsForScopedGlobals(IntellisenseData.IntellisenseData intellisenseData) { Contracts.AssertValue(intellisenseData); var suggestions = intellisenseData.AdditionalGlobalSuggestions .Union(intellisenseData.EnumSymbols.Select(symbol => new KeyValuePair <string, SuggestionIconKind>(symbol.Name, SuggestionIconKind.Other))); IntellisenseHelper.AddSuggestionsForMatches(intellisenseData, suggestions, SuggestionKind.Global, requiresSuggestionEscaping: true); }
/// <summary> /// Suggest possibilities that can come after a value of a certain type. /// </summary> internal static void AddSuggestionsForAfterValue(IntellisenseData.IntellisenseData intellisenseData, DType type) { Contracts.AssertValue(intellisenseData); Contracts.AssertValid(type); intellisenseData.Suggestions.Clear(); intellisenseData.SubstringSuggestions.Clear(); intellisenseData.SetMatchArea(intellisenseData.ReplacementStartIndex, intellisenseData.ReplacementStartIndex); AddSuggestionsForMatches(intellisenseData, TexlLexer.LocalizedInstance.GetOperatorKeywords(type), SuggestionKind.BinaryOperator, SuggestionIconKind.Other, requiresSuggestionEscaping: false); }
internal static void AddSuggestionsForMatches(IntellisenseData.IntellisenseData intellisenseData, IEnumerable <KeyValuePair <string, SuggestionIconKind> > possibilities, SuggestionKind kind, bool requiresSuggestionEscaping, uint sortPriority = 0) { Contracts.AssertValue(intellisenseData); Contracts.AssertValue(possibilities); foreach (var possibility in possibilities) { AddSuggestion(intellisenseData, possibility.Key, kind, possibility.Value, DType.Unknown, requiresSuggestionEscaping, sortPriority); } }
private static void AddSuggestionsForScopeFields(IntellisenseData.IntellisenseData intellisenseData, DType scope) { Contracts.AssertValue(intellisenseData); Contracts.Assert(scope.IsValid); foreach (var field in scope.GetNames(DPath.Root)) { IntellisenseHelper.AddSuggestion(intellisenseData, TexlLexer.PunctuatorAt + TexlLexer.EscapeName(field.Name.Value), SuggestionKind.Field, SuggestionIconKind.Other, field.Type, requiresSuggestionEscaping: false); } }
internal override bool TryAddSuggestionsForNodeKind(IntellisenseData.IntellisenseData intellisenseData) { Contracts.AssertValue(intellisenseData); TexlNode curNode = intellisenseData.CurNode; int cursorPos = intellisenseData.CursorPos; // Cursor position is after the dot (If it was before the dot FindNode would have returned the left node). Contracts.Assert(curNode.Token.IsDottedNamePunctuator); Contracts.Assert(curNode.Token.Span.Lim <= cursorPos); DottedNameNode dottedNameNode = curNode.CastDottedName(); Identifier ident = dottedNameNode.Right; string identName = ident.Name; var leftNode = dottedNameNode.Left; DType leftType = intellisenseData.Binding.GetType(leftNode); intellisenseData.BeforeAddSuggestionsForDottedNameNode(leftNode); bool isOneColumnTable = leftType.IsColumn && leftNode.Kind == NodeKind.DottedName && leftType.Accepts(intellisenseData.Binding.GetType(((DottedNameNode)leftNode).Left)); if (cursorPos < ident.Token.Span.Min) { // Cursor position is before the identifier starts. // i.e. "this. | Awards" AddSuggestionsForLeftNodeScope(intellisenseData, leftNode, isOneColumnTable, leftType); } else if (cursorPos <= ident.Token.Span.Lim) { // Cursor position is in the identifier. // Suggest fields that don't need to be qualified. // Identifiers can include open and close brackets and the Token.Span covers them. // Get the matching string as a substring from the script so that the whitespace is preserved. intellisenseData.SetMatchArea(ident.Token.Span.Min, cursorPos, ident.Token.Span.Lim - ident.Token.Span.Min); if (!intellisenseData.Binding.ErrorContainer.HasErrors(dottedNameNode)) { intellisenseData.BoundTo = identName; } AddSuggestionsForLeftNodeScope(intellisenseData, leftNode, isOneColumnTable, leftType); } else if (IntellisenseHelper.CanSuggestAfterValue(cursorPos, intellisenseData.Script)) { // Verify that cursor is after a space after the identifier. // i.e. "this.Awards |" // Suggest binary operators. IntellisenseHelper.AddSuggestionsForAfterValue(intellisenseData, intellisenseData.Binding.GetType(dottedNameNode)); } return(true); }
/// <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 (intellisenseData.CurNode != null) { return(false); } return(IntellisenseHelper.AddSuggestionsForValuePossibilities(intellisenseData, null)); }
public static void AddSuggestionsForEnums(IntellisenseData.IntellisenseData intellisenseData) { Contracts.AssertValue(intellisenseData); var suggestions = intellisenseData.Suggestions; var substringSuggestions = intellisenseData.SubstringSuggestions; int countSuggBefore = suggestions.Count; int countSubSuggBefore = substringSuggestions.Count; foreach (var enumInfo in intellisenseData.EnumSymbols) { var enumType = enumInfo.EnumType; var enumName = enumInfo.Name; // TASK: 76039: Intellisense: Update intellisense to filter suggestions based on the expected type of the text being typed in UI IntellisenseHelper.AddSuggestion(intellisenseData, enumName, SuggestionKind.Enum, SuggestionIconKind.Other, enumType, requiresSuggestionEscaping: true); IntellisenseHelper.AddSuggestionsForEnum(intellisenseData, enumInfo, prefix: enumName + TexlLexer.PunctuatorDot); } if (suggestions.Count + substringSuggestions.Count == countSuggBefore + countSubSuggBefore + 1 && intellisenseData.SuggestUnqualifiedEnums) { string enumSuggestion = suggestions.Count > countSuggBefore ? suggestions[countSuggBefore].Text : substringSuggestions[countSubSuggBefore].Text; int dotIndex = enumSuggestion.LastIndexOf(TexlLexer.PunctuatorDot); // Assert '.' is not present or not at the beginning or the end of the EnumSuggestion Contracts.Assert(dotIndex == -1 || (0 < dotIndex && dotIndex < enumSuggestion.Length - 1)); var unqualifiedEnum = enumSuggestion.Substring(dotIndex + 1); // If the Enum we are about suggest unqualified (i.e. just 'Blue' instead of Color!Blue) // has a name collision with some Item already in the suggestionlist we should not continue // and suggest it. if (suggestions.Any(x => x.Text == unqualifiedEnum) || substringSuggestions.Any(x => x.Text == unqualifiedEnum)) { return; } DType enumType; if (suggestions.Count > countSuggBefore) { enumType = suggestions[countSuggBefore].Type; suggestions.RemoveAt(suggestions.Count - 1); } else { Contracts.Assert(substringSuggestions.Count > countSubSuggBefore); enumType = substringSuggestions[countSubSuggBefore].Type; substringSuggestions.RemoveAt(substringSuggestions.Count - 1); } // Add the unqualified Enum. // Note: The suggestion has already been escaped when it was previously added IntellisenseHelper.AddSuggestion(intellisenseData, unqualifiedEnum, SuggestionKind.Enum, SuggestionIconKind.Other, enumType, requiresSuggestionEscaping: false); } }
/// <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); Contracts.AssertValue(intellisenseData.CurNode); if (intellisenseData.CurNode.Kind != _kind) { return(false); } return(TryAddSuggestionsForNodeKind(intellisenseData)); }
internal static void AddSuggestionsForNamespace(IntellisenseData.IntellisenseData intellisenseData, IEnumerable <TexlFunction> namespaceFunctions) { Contracts.AssertValue(intellisenseData); Contracts.AssertValue(namespaceFunctions); Contracts.AssertAllValues(namespaceFunctions); foreach (var function in namespaceFunctions) { // Note we're using the unqualified name, since we're on the RHS of a "namespace." identifier. AddSuggestion(intellisenseData, function.Name, SuggestionKind.Function, SuggestionIconKind.Function, function.ReturnType, requiresSuggestionEscaping: true); } }
private DType GetAggregateType(TexlFunction func, CallNode callNode, IntellisenseData.IntellisenseData intellisenseData) { Contracts.AssertValue(func); Contracts.AssertValue(callNode); Contracts.AssertValue(intellisenseData); if (intellisenseData.TryGetSpecialFunctionType(func, callNode, out var type)) { return(type); } return(intellisenseData.Binding.GetType(callNode.Args.Children[0])); }
/// <summary> /// Adds suggestions that start with the matchingString from the top level scope of the binding. /// </summary> internal static void AddSuggestionsForRuleScope(IntellisenseData.IntellisenseData intellisenseData) { Contracts.AssertValue(intellisenseData); Contracts.AssertValue(intellisenseData.Binding); var scopeType = intellisenseData.ContextScope; if (scopeType == null) { return; } IntellisenseHelper.AddTopLevelSuggestions(intellisenseData, scopeType); }
public bool Run(IntellisenseData.IntellisenseData intellisenseData) { Contracts.AssertValue(intellisenseData); var cursorPos = intellisenseData.CursorPos; var isCursorInsideComment = intellisenseData.Comments.Where(com => com.Span.Min <= cursorPos && com.Span.Lim >= cursorPos).Any(); if (isCursorInsideComment) { // No intellisense for editing comment return(true); } return(false); }
/// <summary> /// Adds suggestions for given argument position. /// Returns true if any function specific suggestions are added to the list. Otherwise false. /// </summary> /// <returns></returns> public static bool TryAddSpecificSuggestionsForGivenArgPosition(IntellisenseData.IntellisenseData intellisenseData, CallNode callNode, int argumentIndex) { Contracts.AssertValue(intellisenseData); Contracts.AssertValue(callNode); Contracts.Assert(argumentIndex >= 0); CallInfo info = intellisenseData.Binding.GetInfo(callNode); Contracts.AssertValue(info); if (callNode.Args.Count < 0 || info.Function == null || !info.Function.HasSuggestionsForParam(argumentIndex)) { return(false); } // Adding suggestions for callNode arguments from the Function's GetArgumentSuggestions method // Keep track of the previous suggestion counts so we can tell whether or not we have added any int countSuggestionsBefore = intellisenseData.Suggestions.Count; int countSubstringSuggestionsBefore = intellisenseData.SubstringSuggestions.Count; // If the function has specific suggestions for the argument, // indicate it to the caller. var function = info.Function; var suggestionKind = intellisenseData.GetFunctionSuggestionKind(function, argumentIndex); bool requiresSuggestionEscaping; ErrorNode err; if (argumentIndex >= 0 && argumentIndex < callNode.Args.Count && ((err = callNode.Args.Children[argumentIndex].AsError()) != null) && err.Token.Span.StartsWith(intellisenseData.Script, "\"")) { intellisenseData.CleanupHandlers.Add(new StringSuggestionHandler(err.Token.Span.Min)); } DType scopeType = ScopeTypeForArgumentSuggestions(callNode, intellisenseData); var argSuggestions = intellisenseData.GetArgumentSuggestions(function, scopeType, argumentIndex, callNode.Args.Children, out requiresSuggestionEscaping); foreach (KeyValuePair <string, DType> suggestion in argSuggestions) { AddSuggestion(intellisenseData, suggestion.Key, suggestionKind, SuggestionIconKind.Function, suggestion.Value, requiresSuggestionEscaping); } return(intellisenseData.Suggestions.Count > countSuggestionsBefore || intellisenseData.SubstringSuggestions.Count > countSubstringSuggestionsBefore); }
// This method has logic to create Types for the TypedNames for a given type // if that type is Table. internal static void AddSuggestionsForDottedName(IntellisenseData.IntellisenseData intellisenseData, DType type) { Contracts.AssertValue(intellisenseData); Contracts.AssertValid(type); if (intellisenseData.TryAddCustomDottedNameSuggestions(type)) { return; } if (!type.IsTable) { IntellisenseHelper.AddTopLevelSuggestions(intellisenseData, type); return; } IntellisenseHelper.AddSuggestionsForNamesInType(type, intellisenseData, createTableSuggestion: true); }
internal override bool TryAddSuggestionsForNodeKind(IntellisenseData.IntellisenseData intellisenseData) { Contracts.AssertValue(intellisenseData); TexlNode curNode = intellisenseData.CurNode; // Cursor is in the operation token. // Suggest binary operators. BinaryOpNode binaryOpNode = curNode.CastBinaryOp(); var tokenSpan = binaryOpNode.Token.Span; string keyword = binaryOpNode.Op == BinaryOp.Error ? tokenSpan.GetFragment(intellisenseData.Script) : TexlParser.GetTokString(binaryOpNode.Token.Kind); int replacementLength = tokenSpan.Min == intellisenseData.CursorPos ? 0 : tokenSpan.Lim - tokenSpan.Min; intellisenseData.SetMatchArea(tokenSpan.Min, intellisenseData.CursorPos, replacementLength); intellisenseData.BoundTo = binaryOpNode.Op == BinaryOp.Error ? string.Empty : keyword; AddSuggestionsForBinaryOperatorKeyWords(intellisenseData); return(true); }
internal static void AddSuggestionsForGlobals(IntellisenseData.IntellisenseData intellisenseData) { Contracts.AssertValue(intellisenseData); intellisenseData.AddCustomSuggestionsForGlobals(); // Suggest function namespaces var namespaces = intellisenseData.Binding.NameResolver.Functions.Select(func => func.Namespace).Distinct(); foreach (var funcNamespace in namespaces) { if (funcNamespace == DPath.Root) { continue; } IntellisenseHelper.AddSuggestion(intellisenseData, funcNamespace.Name, SuggestionKind.Global, SuggestionIconKind.Other, DType.Unknown, requiresSuggestionEscaping: true); } }
/// <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 bool AddSuggestionsForValuePossibilities(IntellisenseData.IntellisenseData intellisenseData, TexlNode node) { Contracts.AssertValue(intellisenseData); Contracts.AssertValue(node); int suggestionCount = intellisenseData.Suggestions.Count() + intellisenseData.SubstringSuggestions.Count(); IntellisenseHelper.AddSuggestionsForRuleScope(intellisenseData); IntellisenseHelper.AddSuggestionsForTopLevel(intellisenseData, node); IntellisenseHelper.AddSuggestionsForFunctions(intellisenseData); intellisenseData.AddSuggestionsForConstantKeywords(); IntellisenseHelper.AddSuggestionsForGlobals(intellisenseData); intellisenseData.AfterAddSuggestionsForGlobals(); IntellisenseHelper.AddSuggestionsForUnaryOperatorKeyWords(intellisenseData); intellisenseData.AfterAddSuggestionsForUnaryOperatorKeywords(); IntellisenseHelper.AddSuggestionsForEnums(intellisenseData); intellisenseData.AddCustomSuggestionsForValuePossibilities(); return(suggestionCount < (intellisenseData.Suggestions.Count() + intellisenseData.SubstringSuggestions.Count())); }
/// <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); } } }
public static DType ScopeTypeForArgumentSuggestions(CallNode callNode, IntellisenseData.IntellisenseData intellisenseData) { Contracts.AssertValue(callNode); Contracts.AssertValue(intellisenseData); var info = intellisenseData.Binding.GetInfo(callNode); if (info.Function.UseParentScopeForArgumentSuggestions) { return(ClosestParentScopeTypeForSuggestions(callNode, intellisenseData)); } if (callNode.Args.Count <= info.Function.SuggestionTypeReferenceParamIndex) { return(DType.Unknown); } TexlNode referenceArg = callNode.Args.Children[info.Function.SuggestionTypeReferenceParamIndex]; return(info.Function.UsesEnumNamespace ? GetEnumType(intellisenseData, referenceArg) : intellisenseData.Binding.GetType(referenceArg)); }