private static async Task <ImmutableArray <INavigateToSearchResult> > FindNavigableDeclaredSymbolInfosAsync( Project project, Document searchDocument, string pattern, CancellationToken cancellationToken) { // If the user created a dotted pattern then we'll grab the last part of the name var(patternName, patternContainerOpt) = PatternMatcher.GetNameAndContainer(pattern); var nameMatcher = PatternMatcher.CreatePatternMatcher(patternName, includeMatchedSpans: true, allowFuzzyMatching: true); var containerMatcherOpt = patternContainerOpt != null ? PatternMatcher.CreateDotSeparatedContainerMatcher(patternContainerOpt) : null; using (nameMatcher) using (containerMatcherOpt) { var nameMatches = ArrayBuilder <PatternMatch> .GetInstance(); var containerMatches = ArrayBuilder <PatternMatch> .GetInstance(); try { return(await FindNavigableDeclaredSymbolInfosAsync( project, searchDocument, nameMatcher, containerMatcherOpt, nameMatches, containerMatches, cancellationToken).ConfigureAwait(false)); } finally { nameMatches.Free(); containerMatches.Free(); } } }
private static async Task <ImmutableArray <ISymbol> > FindSourceDeclarationsWithPatternInCurrentProcessAsync( string pattern, Func <SearchQuery, Task <ImmutableArray <ISymbol> > > searchAsync) { // 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(namePart, containerPart) = PatternMatcher.GetNameAndContainer(pattern); // If we don't have a dot in the pattern, just make a pattern matcher for the entire // pattern they passed in. Otherwise, make a pattern matcher just for the part after // the dot. using var nameMatcher = PatternMatcher.CreatePatternMatcher(namePart, includeMatchedSpans: false); using var query = SearchQuery.CreateCustom(nameMatcher.Matches); var symbolAndProjectIds = await searchAsync(query).ConfigureAwait(false); if (symbolAndProjectIds.Length == 0 || containerPart == null) { // If it wasn't a dotted pattern, or we didn't get anything back, then we're done. // We can just return whatever set of results we got so far. return(symbolAndProjectIds); } // Ok, we had a dotted pattern. Have to see if the symbol's container matches the // pattern as well. using var containerPatternMatcher = PatternMatcher.CreateDotSeparatedContainerMatcher(containerPart); return(symbolAndProjectIds.WhereAsArray(t => containerPatternMatcher.Matches(GetContainer(t)))); }
private static IEnumerable <PatternMatch> TryMatchMultiWordPattern( string candidate, string pattern ) { MarkupTestFile.GetSpans( candidate, out candidate, out ImmutableArray <TextSpan> expectedSpans ); using var matchesDisposer = ArrayBuilder <PatternMatch> .GetInstance(out var matches); PatternMatcher .CreatePatternMatcher(pattern, includeMatchedSpans: true) .AddMatches(candidate, matches); if (matches.Count == 0) { Assert.True(expectedSpans.Length == 0); return(null); } else { var actualSpans = matches .SelectMany(m => m.MatchedSpans) .OrderBy(s => s.Start) .ToList(); Assert.Equal(expectedSpans, actualSpans); return(matches.ToImmutable()); } }
private static async Task <ImmutableArray <INavigateToSearchResult> > FindSearchResultsAsync( Project project, ImmutableArray <Document> priorityDocuments, Document searchDocument, string pattern, IImmutableSet <string> kinds, CancellationToken cancellationToken) { // If the user created a dotted pattern then we'll grab the last part of the name var(patternName, patternContainerOpt) = PatternMatcher.GetNameAndContainer(pattern); var nameMatcher = PatternMatcher.CreatePatternMatcher(patternName, includeMatchedSpans: true, allowFuzzyMatching: true); var containerMatcherOpt = patternContainerOpt != null ? PatternMatcher.CreateDotSeparatedContainerMatcher(patternContainerOpt) : null; using (nameMatcher) using (containerMatcherOpt) { using var _1 = ArrayBuilder <PatternMatch> .GetInstance(out var nameMatches); using var _2 = ArrayBuilder <PatternMatch> .GetInstance(out var containerMatches); var declaredSymbolInfoKindsSet = new DeclaredSymbolInfoKindSet(kinds); var searchResults = await ComputeSearchResultsAsync( project, priorityDocuments, searchDocument, nameMatcher, containerMatcherOpt, declaredSymbolInfoKindsSet, nameMatches, containerMatches, cancellationToken).ConfigureAwait(false); return(ImmutableArray <INavigateToSearchResult> .CastUp(searchResults)); } }
private static async Task <ImmutableArray <INavigateToSearchResult> > FindSearchResultsAsync( Project project, ImmutableArray <Document> priorityDocuments, Document searchDocument, string pattern, IImmutableSet <string> kinds, CancellationToken cancellationToken) { // If the user created a dotted pattern then we'll grab the last part of the name var(patternName, patternContainerOpt) = PatternMatcher.GetNameAndContainer(pattern); var nameMatcher = PatternMatcher.CreatePatternMatcher(patternName, includeMatchedSpans: true, allowFuzzyMatching: true); var containerMatcherOpt = patternContainerOpt != null ? PatternMatcher.CreateDotSeparatedContainerMatcher(patternContainerOpt) : null; using (nameMatcher) using (containerMatcherOpt) { var nameMatches = ArrayBuilder <PatternMatch> .GetInstance(); var containerMatches = ArrayBuilder <PatternMatch> .GetInstance(); try { var declaredSymbolInfoKindsSet = new DeclaredSymbolInfoKindSet(kinds); // If we're searching a single document, then just do a full search of // that document (we're fast enough to not need to optimize that case). // // If, however, we are searching a project, then see if we could potentially // use the last computed results we have for that project. If so, it can // be much faster to reuse and filter that result than to compute it from // scratch. #if true var task = searchDocument != null ? ComputeSearchResultsAsync(project, priorityDocuments, searchDocument, nameMatcher, containerMatcherOpt, declaredSymbolInfoKindsSet, nameMatches, containerMatches, cancellationToken) : TryFilterPreviousSearchResultsAsync(project, priorityDocuments, searchDocument, pattern, nameMatcher, containerMatcherOpt, declaredSymbolInfoKindsSet, nameMatches, containerMatches, cancellationToken); #else var task = ComputeSearchResultsAsync(project, searchDocument, nameMatcher, containerMatcherOpt, declaredSymbolInfoKindsSet, nameMatches, containerMatches, cancellationToken); #endif var searchResults = await task.ConfigureAwait(false); return(ImmutableArray <INavigateToSearchResult> .CastUp(searchResults)); } finally { nameMatches.Free(); containerMatches.Free(); } } }
private static PatternMatch?TestNonFuzzyMatch(string candidate, string pattern) { MarkupTestFile.GetSpans(candidate, out candidate, out ImmutableArray <TextSpan> spans); var match = PatternMatcher.CreatePatternMatcher(pattern, includeMatchedSpans: true, allowFuzzyMatching: false) .GetFirstMatch(candidate); if (match == null) { Assert.True(spans.Length == 0); } else { Assert.Equal <TextSpan>(match.Value.MatchedSpans, spans); } return(match); }