internal static async Task<IEnumerable<ValueTuple<DeclaredSymbolInfo, Document, IEnumerable<PatternMatch>>>> FindNavigableDeclaredSymbolInfos(Project project, string pattern, CancellationToken cancellationToken)
        {
            var patternMatcher = new PatternMatcher(pattern);

            var result = new List<ValueTuple<DeclaredSymbolInfo, Document, IEnumerable<PatternMatch>>>();
            foreach (var document in project.Documents)
            {
                cancellationToken.ThrowIfCancellationRequested();
                var declaredSymbolInfos = await document.GetDeclaredSymbolInfosAsync(cancellationToken).ConfigureAwait(false);
                foreach (var declaredSymbolInfo in declaredSymbolInfos)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    var patternMatches = patternMatcher.GetMatches(
                        GetSearchName(declaredSymbolInfo),
                        declaredSymbolInfo.FullyQualifiedContainerName,
                        includeMatchSpans: false);

                    if (patternMatches != null)
                    {
                        result.Add(ValueTuple.Create(declaredSymbolInfo, document, patternMatches));
                    }
                }
            }

            return result;
        }
        private static async Task<ImmutableArray<ValueTuple<DeclaredSymbolInfo, Document, IEnumerable<PatternMatch>>>> FindNavigableDeclaredSymbolInfos(
            Project project, Document searchDocument, string pattern, CancellationToken cancellationToken)
        {
            using (var patternMatcher = new PatternMatcher(pattern, allowFuzzyMatching: true))
            {
                var result = ArrayBuilder<ValueTuple<DeclaredSymbolInfo, Document, IEnumerable<PatternMatch>>>.GetInstance();
                foreach (var document in project.Documents)
                {
                    if (searchDocument != null && document != searchDocument)
                    {
                        continue;
                    }

                    cancellationToken.ThrowIfCancellationRequested();
                    var declarationInfo = await document.GetDeclarationInfoAsync(cancellationToken).ConfigureAwait(false);

                    foreach (var declaredSymbolInfo in declarationInfo.DeclaredSymbolInfos)
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                        var patternMatches = patternMatcher.GetMatches(
                            GetSearchName(declaredSymbolInfo),
                            declaredSymbolInfo.FullyQualifiedContainerName,
                            includeMatchSpans: false);

                        if (patternMatches != null)
                        {
                            result.Add(ValueTuple.Create(declaredSymbolInfo, document, patternMatches));
                        }
                    }
                }

                return result.ToImmutableAndFree();
            }
        }
        internal static async Task<IEnumerable<ValueTuple<DeclaredSymbolInfo, Document, IEnumerable<PatternMatch>>>> FindNavigableDeclaredSymbolInfos(Project project, string pattern, CancellationToken cancellationToken)
        {
            var generatedCodeRecognitionService = project.LanguageServices.WorkspaceServices.GetService<IGeneratedCodeRecognitionService>();
            var patternMatcher = new PatternMatcher(pattern);

            var result = new List<ValueTuple<DeclaredSymbolInfo, Document, IEnumerable<PatternMatch>>>();
            foreach (var document in project.Documents.Where(d => !generatedCodeRecognitionService?.IsGeneratedCode(d) ?? true))
            {
                cancellationToken.ThrowIfCancellationRequested();
                var declaredSymbolInfos = await document.GetDeclaredSymbolInfosAsync(cancellationToken).ConfigureAwait(false);
                foreach (var declaredSymbolInfo in declaredSymbolInfos)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    var patternMatches = patternMatcher.GetMatches(
                        GetSearchName(declaredSymbolInfo),
                        declaredSymbolInfo.FullyQualifiedContainerName);

                    if (patternMatches != null)
                    {
                        result.Add(ValueTuple.Create(declaredSymbolInfo, document, patternMatches));
                    }
                }
            }

            return result;
        }
示例#4
0
        private static IEnumerable<PatternMatch> TryGetDotSeparatedPatternMatches(
            PatternMatcher patternMatcher,
            string[] dotSeparatedPatternComponents,
            DeclaredSymbolInfo declaredSymbolInfo)
        {
            if (dotSeparatedPatternComponents == null || declaredSymbolInfo.FullyQualifiedContainerName == null || declaredSymbolInfo.Name == null)
            {
                return null;
            }

            // First, check that the last part of the dot separated pattern matches the name of the
            // declared symbol.  If not, then there's no point in proceeding and doing the more
            // expensive work.
            var symbolNameMatch = patternMatcher.MatchPattern(GetSearchName(declaredSymbolInfo), dotSeparatedPatternComponents.Last());
            if (symbolNameMatch == null)
            {
                return null;
            }

            // So far so good.  Now break up the container for the symbol and check if all
            // the dotted parts match up correctly.
            var totalMatch = symbolNameMatch.ToList();

            var containerParts = declaredSymbolInfo.FullyQualifiedContainerName
                .Split(DotArray, StringSplitOptions.RemoveEmptyEntries)
                .ToList();

            // -1 because the last part was checked against hte name, and only the rest
            // of the parts are checked against the container.
            if (dotSeparatedPatternComponents.Length - 1 > containerParts.Count)
            {
                // There weren't enough container parts to match against the pattern parts.
                // So this definitely doesn't match.
                return null;
            }

            for (int i = dotSeparatedPatternComponents.Length - 2, j = containerParts.Count - 1;
                    i >= 0;
                    i--, j--)
            {
                var dotPattern = dotSeparatedPatternComponents[i];
                var containerName = containerParts[j];
                var containerMatch = patternMatcher.MatchPattern(containerName, dotPattern);
                if (containerMatch == null)
                {
                    // This container didn't match the pattern piece.  So there's no match at all.
                    return null;
                }

                totalMatch.AddRange(containerMatch);
            }

            // Success, this symbol's full name matched against the dotted name the user was asking
            // about.
            return totalMatch;
        }
            protected PatternMatcher GetPatternMatcher(string value)
            {
                lock (_gate)
                {
                    PatternMatcher patternMatcher;
                    if (!_patternMatcherMap.TryGetValue(value, out patternMatcher))
                    {
                        patternMatcher = new PatternMatcher(value, verbatimIdentifierPrefixIsWordCharacter: true);
                        _patternMatcherMap.Add(value, patternMatcher);
                    }

                    return patternMatcher;
                }
            }
 public Searcher(
     Solution solution,
     IAsynchronousOperationListener asyncListener,
     ItemDisplayFactory displayFactory,
     INavigateToCallback callback,
     string searchPattern,
     CancellationToken cancellationToken)
 {
     _solution = solution;
     _displayFactory = displayFactory;
     _callback = callback;
     _searchPattern = searchPattern;
     _patternMatcher = new PatternMatcher();
     _cancellationToken = cancellationToken;
     _progress = new ProgressTracker(callback.ReportProgress);
     _asyncListener = asyncListener;
 }
示例#7
0
        private static IEnumerable<PatternMatch> TryMatch(
            string pattern,
            string[] dotSeparatedPatternComponents,
            PatternMatcher patternMatcher,
            DeclaredSymbolInfo declaredSymbolInfo)
        {
            var matches1 = TryGetDotSeparatedPatternMatches(patternMatcher, dotSeparatedPatternComponents, declaredSymbolInfo);
            var matches2 = patternMatcher.MatchPattern(GetSearchName(declaredSymbolInfo), pattern);

            if (matches1 == null)
            {
                return matches2;
            }

            if (matches2 == null)
            {
                return matches1;
            }

            return matches1.Concat(matches2);
        }
示例#8
0
        internal static async Task<IEnumerable<ValueTuple<DeclaredSymbolInfo, Document, IEnumerable<PatternMatch>>>> FindNavigableDeclaredSymbolInfos(Project project, string pattern, CancellationToken cancellationToken)
        {
            var patternMatcher = new PatternMatcher();
            var dotSeparatedPatternComponents = pattern.Contains(".") ? pattern.Split(DotArray, StringSplitOptions.RemoveEmptyEntries) : null;

            var result = new List<ValueTuple<DeclaredSymbolInfo, Document, IEnumerable<PatternMatch>>>();
            foreach (var document in project.Documents)
            {
                cancellationToken.ThrowIfCancellationRequested();
                var declaredSymbolInfos = await document.GetDeclaredSymbolInfosAsync(cancellationToken).ConfigureAwait(false);
                foreach (var declaredSymbolInfo in declaredSymbolInfos)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    var patternMatches = TryMatch(pattern, dotSeparatedPatternComponents, patternMatcher, declaredSymbolInfo);
                    if (patternMatches != null)
                    {
                        result.Add(ValueTuple.Create(declaredSymbolInfo, document, patternMatches));
                    }
                }
            }

            return result;
        }
示例#9
0
        private static IEnumerable<PatternMatch> TryMatchMultiWordPattern(string candidate, string pattern)
        {
            IList<TextSpan> expectedSpans;
            MarkupTestFile.GetSpans(candidate, out candidate, out expectedSpans);

            var matches = new PatternMatcher(pattern).GetMatches(candidate, includeMatchSpans: true);

            if (matches == null)
            {
                Assert.True(expectedSpans == null || expectedSpans.Count == 0);
            }
            else
            {
                var actualSpans = matches.SelectMany(m => m.MatchedSpans).OrderBy(s => s.Start).ToList();
                Assert.Equal(expectedSpans, actualSpans);
            }

            return matches;
        }
示例#10
0
        private static PatternMatch? TryMatchSingleWordPattern(string candidate, string pattern)
        {
            IList<TextSpan> spans;
            MarkupTestFile.GetSpans(candidate, out candidate, out spans);

            var match = new PatternMatcher(pattern).MatchSingleWordPattern_ForTestingOnly(candidate);

            if (match == null)
            {
                Assert.True(spans == null || spans.Count == 0);
            }
            else
            {
                Assert.Equal(match.Value.MatchedSpans, spans);
            }

            return match;
        }
示例#11
0
        private PatternMatcher GetFallbackPatternMatcher(string value)
        {
            lock (_gate)
            {
                PatternMatcher patternMatcher;
                if (!_fallbackPatternMatcherMap.TryGetValue(value, out patternMatcher))
                {
                    patternMatcher = new PatternMatcher(value, EnUSCultureInfo, verbatimIdentifierPrefixIsWordCharacter: true);
                    _fallbackPatternMatcherMap.Add(value, patternMatcher);
                }

                return patternMatcher;
            }
        }
示例#12
0
        private PatternMatcher GetPatternMatcher(
            string value, CultureInfo culture, Dictionary<CultureInfo, Dictionary<string, PatternMatcher>> map)
        {
            lock (_gate)
            {
                Dictionary<string, PatternMatcher> innerMap;
                if (!map.TryGetValue(culture, out innerMap))
                {
                    innerMap = new Dictionary<string, PatternMatcher>();
                    map[culture] = innerMap;
                }

                PatternMatcher patternMatcher;
                if (!innerMap.TryGetValue(value, out patternMatcher))
                {
                    patternMatcher = new PatternMatcher(value, culture,
                        verbatimIdentifierPrefixIsWordCharacter: true,
                        allowFuzzyMatching: false);
                    innerMap.Add(value, patternMatcher);
                }

                return patternMatcher;
            }
        }
示例#13
0
        internal async Task<IEnumerable<ValueTuple<ISymbol, IEnumerable<PatternMatch>>>> FindNavigableSourceSymbolsAsync(
            Project project, CancellationToken cancellationToken)
        {
            var results = new List<ValueTuple<ISymbol, IEnumerable<PatternMatch>>>();

            // The compiler API only supports a predicate which is given a symbol's name.  Because
            // we only have the name, and nothing else, we need to check it against the last segment
            // of the pattern.  i.e. if the pattern is 'Console.WL' and we are given 'WriteLine', then
            // we don't want to check the whole pattern against it (as it will clearly fail), instead
            // we only want to check the 'WL' portion.  Then, after we get all the candidate symbols
            // we'll check if the full name matches the full pattern.
            var patternMatcher = new PatternMatcher(_searchPattern);
            var symbols = await SymbolFinder.FindSourceDeclarationsAsync(
                project, k => patternMatcher.GetMatchesForLastSegmentOfPattern(k) != null, SymbolFilter.TypeAndMember, cancellationToken).ConfigureAwait(false);

            symbols = symbols.Where(s =>
                !s.IsConstructor()
                && !s.IsStaticConstructor() // not constructors, they get matched on type name
                && !(s is INamespaceSymbol) // not namespaces
                && s.Locations.Any(loc => loc.IsInSource)); // only source symbols

            foreach (var symbol in symbols)
            {
                cancellationToken.ThrowIfCancellationRequested();

                // As an optimization, don't bother getting the container for this symbol if this
                // isn't a dotted pattern.  Getting the container could cause lots of string 
                // allocations that we don't if we're never going to check it.
                var matches = !patternMatcher.IsDottedPattern
                    ? patternMatcher.GetMatches(GetSearchName(symbol))
                    : patternMatcher.GetMatches(GetSearchName(symbol), GetContainer(symbol));

                if (matches == null)
                {
                    continue;
                }

                results.Add(ValueTuple.Create(symbol, matches));

                // also report matching constructors (using same match result as type)
                var namedType = symbol as INamedTypeSymbol;
                if (namedType != null)
                {
                    foreach (var constructor in namedType.Constructors)
                    {
                        // only constructors that were explicitly declared
                        if (!constructor.IsImplicitlyDeclared)
                        {
                            results.Add(ValueTuple.Create((ISymbol)constructor, matches));
                        }
                    }
                }

                // report both parts of partial methods
                var method = symbol as IMethodSymbol;
                if (method != null && method.PartialImplementationPart != null)
                {
                    results.Add(ValueTuple.Create((ISymbol)method, matches));
                }
            }

            return results;
        }