Beispiel #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);
            }
        }
Beispiel #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());
        }
Beispiel #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);
        }
Beispiel #4
0
        public LanguageSettings(string cultureName, string uiCultureName, bool addPunctuators = false)
        {
            Contracts.AssertNonEmpty(cultureName);

            _cultureName   = cultureName;
            _uiCultureName = uiCultureName;

            _locToInvariantFunctionMap   = new Dictionary <string, string>();
            _locToInvariantPunctuatorMap = new Dictionary <string, string>();
            _invariantToLocFunctionMap   = new Dictionary <string, string>();
            _invariantToLocPunctuatorMap = new Dictionary <string, string>();

            _cacheStamp = 0;
            _cachedInvariantSettings = null;

            if (addPunctuators)
            {
                string dec;
                string comma;
                string list;
                TexlLexer.ChoosePunctuators(this, out dec, out comma, out list);
                AddPunctuator(dec, TexlLexer.PunctuatorDecimalSeparatorInvariant);
                AddPunctuator(comma, TexlLexer.PunctuatorCommaInvariant);
                AddPunctuator(list, TexlLexer.PunctuatorSemicolonInvariant);
            }
        }
Beispiel #5
0
        // Parses a typed name map specification, returns true and sets 'map' on success.
        // A map specification has the form: [name:type, ...]
        private static bool TryParseTypeMap(DTypeSpecLexer lexer, out TypeTree map)
        {
            Contracts.AssertValue(lexer);

            string token;

            if (!lexer.TryNextToken(out token) || token != "[")
            {
                map = default(TypeTree);
                return(false);
            }

            map = new TypeTree();

            while (lexer.TryNextToken(out token) && token != "]")
            {
                string name = token;
                if (name.Length >= 2 && name.StartsWith("'") && name.EndsWith("'"))
                {
                    name = TexlLexer.UnescapeName(name);
                }

                DType type;
                if (!DName.IsValidDName(name) ||
                    !lexer.TryNextToken(out token) ||
                    token != ":" ||
                    map.Contains(name) ||
                    !TryParse(lexer, out type))
                {
                    map = default(TypeTree);
                    return(false);
                }

                map = map.SetItem(name, type);

                if (!lexer.TryNextToken(out token) || (token != "," && token != "]"))
                {
                    map = default(TypeTree);
                    return(false);
                }
                else if (token == "]")
                {
                    return(true);
                }
            }

            if (token != "]")
            {
                map = default(TypeTree);
                return(false);
            }

            return(true);
        }
Beispiel #6
0
        private static Token[] TokenizeScript(string script, ILanguageSettings loc = null, Flags flags = Flags.None)
        {
            Contracts.AssertValue(script);
            Contracts.AssertValueOrNull(loc);

            TexlLexer.Flags lexerFlags = flags.HasFlag(Flags.AllowReplaceableExpressions) ? TexlLexer.Flags.AllowReplaceableTokens : TexlLexer.Flags.None;

            if (loc == null)
            {
                return(TexlLexer.LocalizedInstance.LexSource(script, lexerFlags));
            }

            return(TexlLexer.NewInstance(loc).LexSource(script, lexerFlags));
        }
Beispiel #7
0
        public void TestIsIdentStart()
        {
            Tuple <char, char>[] identStartRanges = new Tuple <char, char>[] {
                Tuple.Create('A', 'Z'),
                Tuple.Create('a', 'z'),
                Tuple.Create('_', '_'),
                Tuple.Create('\'', '\''),
            };

            for (int i = 0; i < 128; i++)
            {
                char ch = (char)i;
                Assert.Equal(LexerTest.IsInRangeInclusive(ch, identStartRanges), TexlLexer.IsIdentStart(ch));
            }
        }
Beispiel #8
0
        public void TestTryNameOrIdentifierToName()
        {
            DName name;

            Assert.True(TexlLexer.TryNameOrIdentifierToName(" Name   ", out name));
            Assert.Equal("Name", name);

            Assert.True(TexlLexer.TryNameOrIdentifierToName(" Name   Abcd ", out name));
            Assert.Equal("Name   Abcd", name);

            Assert.True(TexlLexer.TryNameOrIdentifierToName(" Name   Abcd", out name));
            Assert.Equal("Name   Abcd", name);

            Assert.True(TexlLexer.TryNameOrIdentifierToName("Name   Abcd", out name));
            Assert.Equal("Name   Abcd", name);

            Assert.True(TexlLexer.TryNameOrIdentifierToName("Name\bAbcd", out name));
            Assert.Equal("Name\bAbcd", name);

            Assert.False(TexlLexer.TryNameOrIdentifierToName(string.Empty, out name));
            Assert.False(TexlLexer.TryNameOrIdentifierToName("   ", out name));

            Assert.True(TexlLexer.TryNameOrIdentifierToName("   'Escaped Name'", out name));
            Assert.Equal("Escaped Name", name);

            Assert.True(TexlLexer.TryNameOrIdentifierToName("   'Escaped '' Name'", out name));
            Assert.Equal("Escaped ' Name", name);

            Assert.True(TexlLexer.TryNameOrIdentifierToName("   'Escaped '' Name'''", out name));
            Assert.Equal("Escaped ' Name'", name);

            Assert.False(TexlLexer.TryNameOrIdentifierToName("   '   ' ", out name));

            Assert.True(TexlLexer.TryNameOrIdentifierToName("   ''''", out name));
            Assert.Equal("'", name);

            Assert.True(TexlLexer.TryNameOrIdentifierToName("   'Escaped Name'   ", out name));
            Assert.Equal("Escaped Name", name);

            Assert.False(TexlLexer.TryNameOrIdentifierToName("   'Escaped Name   ", out name));
            Assert.False(TexlLexer.TryNameOrIdentifierToName("   'Escaped Name  ' abc ", out name));

            Assert.True(TexlLexer.TryNameOrIdentifierToName("   '#a!>>?'", out name));
            Assert.Equal("#a!>>?", name);

            Assert.True(TexlLexer.TryNameOrIdentifierToName("   '123\u00ae'", out name));
            Assert.Equal("123\u00ae", name);
        }
Beispiel #9
0
        public void TestLexNumbersWithLanguageSettings()
        {
            Token[] tokens;

            tokens = TexlLexer.NewInstance(SomeFrenchLikeSettings()).LexSource("123456,78");
            Assert.NotNull(tokens);
            Assert.Equal(2, tokens.Length);
            Assert.Equal(TokKind.NumLit, tokens[0].Kind);
            Assert.Equal(123456.78, tokens[0].As <NumLitToken>().Value);

            tokens = TexlLexer.NewInstance(SomeRomanianLikeSettings()).LexSource("10`12345");
            Assert.NotNull(tokens);
            Assert.Equal(2, tokens.Length);
            Assert.Equal(TokKind.NumLit, tokens[0].Kind);
            Assert.Equal(10.12345, tokens[0].As <NumLitToken>().Value);
        }
Beispiel #10
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)));
        }
Beispiel #11
0
        public void TestLexListsWithLanguageSettings()
        {
            Token[] tokens;

            tokens = TexlLexer.NewInstance(SomeFrenchLikeSettings()).LexSource("[1,2;2,3;4]");
            Assert.NotNull(tokens);
            Assert.Equal(8, tokens.Length);
            Assert.Equal(TokKind.BracketOpen, tokens[0].Kind);
            Assert.Equal(TokKind.NumLit, tokens[1].Kind);
            Assert.Equal(1.2, tokens[1].As <NumLitToken>().Value);
            Assert.Equal(TokKind.Comma, tokens[2].Kind);
            Assert.Equal(TokKind.NumLit, tokens[3].Kind);
            Assert.Equal(2.3, tokens[3].As <NumLitToken>().Value);
            Assert.Equal(TokKind.Comma, tokens[4].Kind);
            Assert.Equal(TokKind.NumLit, tokens[5].Kind);
            Assert.Equal(4, tokens[5].As <NumLitToken>().Value);
            Assert.Equal(TokKind.BracketClose, tokens[6].Kind);
            Assert.Equal(TokKind.Eof, tokens[7].Kind);
        }
Beispiel #12
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);
                }
            }
        }
Beispiel #13
0
        public void TestLexSemicolonListsWithLanguageSettings()
        {
            Token[] tokens;

            tokens = TexlLexer.NewInstance(SomeFrenchLikeSettings()).LexSource("A ;; B ;; C");
            Assert.NotNull(tokens);
            Assert.Equal(10, tokens.Length);
            Assert.Equal(TokKind.Ident, tokens[0].Kind);
            Assert.Equal("A", tokens[0].As <IdentToken>().Name.Value);
            Assert.Equal(TokKind.Whitespace, tokens[1].Kind);
            Assert.Equal(TokKind.Semicolon, tokens[2].Kind);
            Assert.Equal(TokKind.Whitespace, tokens[3].Kind);
            Assert.Equal(TokKind.Ident, tokens[4].Kind);
            Assert.Equal("B", tokens[4].As <IdentToken>().Name.Value);
            Assert.Equal(TokKind.Whitespace, tokens[5].Kind);
            Assert.Equal(TokKind.Semicolon, tokens[6].Kind);
            Assert.Equal(TokKind.Whitespace, tokens[7].Kind);
            Assert.Equal(TokKind.Ident, tokens[8].Kind);
            Assert.Equal("C", tokens[8].As <IdentToken>().Name.Value);
            Assert.Equal(TokKind.Eof, tokens[9].Kind);
        }
Beispiel #14
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());
            }
        }
Beispiel #15
0
        internal bool SetMatchArea(int startIndex, int endIndex, int replacementLength = -1)
        {
            Contracts.Assert(0 <= startIndex && startIndex <= endIndex && endIndex <= _script.Length);

            // If we have already provided suggestions, we can't set the match area
            if (Suggestions.Count > 0 || SubstringSuggestions.Count > 0)
            {
                return(false);
            }

            // Trim leading whitespace as there is no point to matching it
            while (startIndex < endIndex && string.IsNullOrWhiteSpace(Script.Substring(startIndex, 1)))
            {
                startIndex++;
            }

            _replacementStartIndex = startIndex;
            _matchingLength        = endIndex - startIndex;
            _replacementLength     = replacementLength < 0 ? _matchingLength : replacementLength;
            _matchingStr           = TexlLexer.UnescapeName(_script.Substring(startIndex, _matchingLength));

            return(true);
        }
Beispiel #16
0
        public void TestUnsupportedDecimalSeparatorCausesFallback()
        {
            Token[] tokens;

            // Simulate an override of the decimal separator to something that AXL does not support.
            var oldCulture = CultureInfo.CurrentCulture;
            var newCulture = new CultureInfo(CultureInfo.CurrentCulture.Name);

            newCulture.NumberFormat.NumberDecimalSeparator = "+";
            CultureInfo.CurrentCulture = newCulture;

            // The lexer should fall back to the invariant separator.
            TexlLexer lexer = TexlLexer.NewInstance(null);

            Assert.Equal(lexer.LocalizedPunctuatorDecimalSeparator, TexlLexer.PunctuatorDecimalSeparatorInvariant);

            tokens = lexer.LexSource("123456.78");
            Assert.NotNull(tokens);
            Assert.Equal(2, tokens.Length);
            Assert.Equal(TokKind.NumLit, tokens[0].Kind);
            Assert.Equal(123456.78, tokens[0].As <NumLitToken>().Value);

            CultureInfo.CurrentCulture = oldCulture;
        }
Beispiel #17
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));
            }
            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);
                }
            }
        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);
        }