Example #1
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);
            }
        }
Example #2
0
        // Convert this DPath to a string in dotted syntax, such as "screen1.group6.label3"
        public string ToDottedSyntax(string punctuator = ".", bool escapeInnerName = false)
        {
            Contracts.AssertNonEmpty(punctuator);
            Contracts.Assert(punctuator.Length == 1);
            Contracts.Assert(".!".IndexOf(punctuator[0]) >= 0);

            if (IsRoot)
            {
                return(string.Empty);
            }

            Contracts.Assert(Length > 0);
            int count = 0;

            for (Node node = _node; node != null; node = node.Parent)
            {
                count += node.Name.Value.Length;
            }

            StringBuilder sb = new StringBuilder(count + Length - 1);

            string sep = string.Empty;

            for (int i = 0; i < Length; i++)
            {
                sb.Append(sep);
                var escapedName = escapeInnerName ? TexlLexer.EscapeName(this[i]) : this[i];
                sb.Append(escapedName);
                sep = punctuator;
            }

            return(sb.ToString());
        }
Example #3
0
        private static IEnumerable <KeyValuePair <string, DType> > TimeUnitSuggestions(TryGetEnumSymbol tryGetEnumSymbol, bool suggestUnqualifedEnums, DType scopeType, int argumentIndex, out bool requiresSuggestionEscaping)
        {
            Contracts.Assert(scopeType.IsValid);
            Contracts.Assert(2 == argumentIndex);

            requiresSuggestionEscaping = false;
            var retVal = new List <KeyValuePair <string, DType> >();

            if (argumentIndex == 2 && tryGetEnumSymbol(EnumConstants.TimeUnitEnumString, out var enumInfo))
            {
                Contracts.AssertValue(enumInfo);
                foreach (var name in enumInfo.EnumType.GetNames(DPath.Root))
                {
                    string locName;
                    enumInfo.TryGetLocValueName(name.Name.Value, out locName).Verify();
                    if (suggestUnqualifedEnums)
                    {
                        retVal.Add(new KeyValuePair <string, DType>(TexlLexer.EscapeName(locName), name.Type));
                    }
                    else
                    {
                        retVal.Add(new KeyValuePair <string, DType>(TexlLexer.EscapeName(enumInfo.Name) + TexlLexer.PunctuatorDot + TexlLexer.EscapeName(locName), name.Type));
                    }
                }
            }

            return(retVal);
        }
Example #4
0
        // This method returns the suggestions for latter arguments of the If function based on the second argument (the true result)
        private static IEnumerable <KeyValuePair <string, DType> > IfSuggestions(TryGetEnumSymbol tryGetEnumSymbol, bool suggestUnqualifedEnums, DType scopeType, int argumentIndex, out bool requiresSuggestionEscaping)
        {
            Contracts.Assert(scopeType.IsValid);
            Contracts.Assert(0 <= argumentIndex);

            requiresSuggestionEscaping = false;

            if (argumentIndex <= 1)
            {
                return(EnumerableUtils.Yield <KeyValuePair <string, DType> >());
            }

            return(scopeType
                   .GetNames(DPath.Root)
                   .Select(name => new KeyValuePair <string, DType>(TexlLexer.EscapeName(name.Name.Value), name.Type)));
        }
Example #5
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);
                }
            }
        }
Example #6
0
        /// <summary>
        /// This method returns the suggestions for second and third arguments of the Text function.
        /// </summary>
        /// <param name="tryGetEnumSymbol">
        /// Getter for enum symbols intended for the suggestions
        /// </param>
        /// <param name="suggestUnescapedEnums">
        /// Whether to suggest unescaped enums
        /// </param>
        /// <param name="scopeType">
        /// Type of the enclosing scope from where intellisense is run
        /// </param>
        /// <param name="argumentIndex">
        /// The current index of the argument from where intellisense is run
        /// </param>
        /// <param name="requiresSuggestionEscaping">
        /// Set to whether the argument needs to be string escaped
        /// </param>
        /// <returns>
        /// Enumerable of suggestions wherein the key is the suggestion text and the value is its type
        /// </returns>
        private static IEnumerable <KeyValuePair <string, DType> > TextSuggestions(TryGetEnumSymbol tryGetEnumSymbol, bool suggestUnescapedEnums, DType scopeType, int argumentIndex, out bool requiresSuggestionEscaping)
        {
            Contracts.Assert(scopeType.IsValid);
            Contracts.Assert(0 <= argumentIndex);

            requiresSuggestionEscaping = true;

            if (argumentIndex != 1 && argumentIndex != 2)
            {
                return(EnumerableUtils.Yield <KeyValuePair <string, DType> >());
            }

            if (argumentIndex == 1)
            {
                if (!DType.DateTime.Accepts(scopeType) || !tryGetEnumSymbol(EnumConstants.DateTimeFormatEnumString, out var enumInfo))
                {
                    return(EnumerableUtils.Yield <KeyValuePair <string, DType> >());
                }

                var retVal = new List <KeyValuePair <string, DType> >();
                Contracts.AssertValue(enumInfo);

                requiresSuggestionEscaping = false;
                foreach (var name in enumInfo.EnumType.GetNames(DPath.Root))
                {
                    string locName;
                    enumInfo.TryGetLocValueName(name.Name.Value, out locName).Verify();
                    retVal.Add(new KeyValuePair <string, DType>(TexlLexer.EscapeName(enumInfo.Name) + TexlLexer.PunctuatorDot + TexlLexer.EscapeName(locName), name.Type));
                }

                return(retVal);
            }
            else
            {
                Contracts.Assert(argumentIndex == 2);

                requiresSuggestionEscaping = false;
                return(GetLanguageCodeSuggestions());
            }
        }
            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);
                }
            }
Example #8
0
        public bool AddSuggestion(IntellisenseData.IntellisenseData intellisenseData, string suggestion, SuggestionKind suggestionKind, SuggestionIconKind iconKind, DType type, bool requiresSuggestionEscaping, uint sortPriority = 0)
        {
            Contracts.AssertValue(intellisenseData);
            Contracts.AssertValue(suggestion);

            if (!intellisenseData.DetermineSuggestibility(suggestion, type))
            {
                return(false);
            }

            IntellisenseSuggestionList suggestions          = intellisenseData.Suggestions;
            IntellisenseSuggestionList substringSuggestions = intellisenseData.SubstringSuggestions;
            int    matchingLength = intellisenseData.MatchingLength;
            string matchingStr    = intellisenseData.MatchingStr;
            string boundTo        = intellisenseData.BoundTo;

            var valueToSuggest = requiresSuggestionEscaping ? TexlLexer.EscapeName(suggestion) : suggestion;
            int highlightStart = suggestion.IndexOf(matchingStr, StringComparison.OrdinalIgnoreCase);

            // If the suggestion has special characters we need to find the highlightStart index by escaping the matching string as well.
            // Because, the suggestion could be something like 'Ident with Space' and the user might have typed Ident. In this case,
            // we want to highlight only Ident while displaying 'Ident with Space'.
            if (requiresSuggestionEscaping && !string.IsNullOrEmpty(matchingStr) && valueToSuggest != suggestion && highlightStart == 0)
            {
                highlightStart++;
            }
            else
            {
                matchingLength--;
            }

            int highlightEnd = highlightStart + matchingStr.Length;

            if (IntellisenseHelper.IsMatch(suggestion, matchingStr))
            {
                // In special circumstance where the user escapes an identifier where they don't have to, the matching length will
                // include the starting delimiter that user provided, where as the suggestion would not include any delimiters.
                // Hence we have to count for that fact.
                if (matchingLength > 0 & matchingLength > matchingStr.Length)
                {
                    highlightEnd = matchingLength > valueToSuggest.Length ? valueToSuggest.Length : matchingLength;
                }
                UIString UIsuggestion            = ConstructUIString(suggestionKind, type, suggestions, valueToSuggest, highlightStart, highlightEnd);
                IntellisenseSuggestion candidate = new IntellisenseSuggestion(UIsuggestion,
                                                                              suggestionKind,
                                                                              iconKind,
                                                                              type,
                                                                              boundTo,
                                                                              -1,
                                                                              string.Empty,
                                                                              null,
                                                                              sortPriority);
                return(CheckAndAddSuggestion(suggestions, candidate));
            }
            if (highlightStart > -1)
            {
                UIString UIsuggestion            = ConstructUIString(suggestionKind, type, substringSuggestions, valueToSuggest, highlightStart, highlightEnd);
                IntellisenseSuggestion candidate = new IntellisenseSuggestion(UIsuggestion,
                                                                              suggestionKind,
                                                                              iconKind,
                                                                              type,
                                                                              boundTo,
                                                                              -1,
                                                                              string.Empty,
                                                                              null,
                                                                              sortPriority);

                return(CheckAndAddSuggestion(substringSuggestions, candidate));
            }

            return(false);
        }
Example #9
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 (!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));
            }