예제 #1
0
        /// <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);
        }
예제 #2
0
        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));
        }
예제 #3
0
        /// <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);
            }
        }
예제 #4
0
        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);
        }
예제 #5
0
        /// <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));
        }
예제 #6
0
        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);
        }
예제 #7
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);
                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);
            }
예제 #10
0
            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);
            }
예제 #12
0
        /// <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);
        }
예제 #13
0
        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);
            }
예제 #16
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 (intellisenseData.CurNode != null)
                {
                    return(false);
                }

                return(IntellisenseHelper.AddSuggestionsForValuePossibilities(intellisenseData, null));
            }
예제 #17
0
        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);
            }
        }
예제 #18
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);
                Contracts.AssertValue(intellisenseData.CurNode);

                if (intellisenseData.CurNode.Kind != _kind)
                {
                    return(false);
                }

                return(TryAddSuggestionsForNodeKind(intellisenseData));
            }
예제 #19
0
        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);
            }
        }
예제 #20
0
            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]));
            }
예제 #21
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);
            }
예제 #23
0
        /// <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);
            }
예제 #26
0
        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);
            }
        }
예제 #27
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);
                }
            }
        }
예제 #28
0
        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()));
        }
예제 #29
0
        /// <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);
                }
            }
        }
예제 #30
0
        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));
        }