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)))); }
/// <summary> /// Find the symbols for declarations made in source with a matching name. /// </summary> public static async Task <IEnumerable <ISymbol> > FindSourceDeclarationsAsync(Project project, Func <string, bool> predicate, SymbolFilter filter, CancellationToken cancellationToken = default(CancellationToken)) { var declarations = await FindSourceDeclarationsWithCustomQueryAsync( project, SearchQuery.CreateCustom(predicate), filter, cancellationToken).ConfigureAwait(false); return(declarations.SelectAsArray(d => d.Symbol)); }
/// <summary> /// Find the symbols for declarations made in source with a matching name. /// </summary> public static async Task <IEnumerable <ISymbol> > FindSourceDeclarationsAsync(Project project, Func <string, bool> predicate, SymbolFilter filter, CancellationToken cancellationToken = default) { using var query = SearchQuery.CreateCustom(predicate); var declarations = await FindSourceDeclarationsWithCustomQueryAsync( project, query, filter, cancellationToken).ConfigureAwait(false); return(declarations); }
internal static async Task <ImmutableArray <SymbolAndProjectId> > FindSourceDeclarationsWithPatternInCurrentProcessAsync( Project project, string pattern, SymbolFilter criteria, CancellationToken cancellationToken) { // 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(pattern); using (var query = SearchQuery.CreateCustom( k => !patternMatcher.GetMatchesForLastSegmentOfPattern(k).IsDefaultOrEmpty)) { var symbolAndProjectIds = await SymbolFinder.FindSourceDeclarationsWithCustomQueryAsync( project, query, criteria, cancellationToken).ConfigureAwait(false); var result = ArrayBuilder <SymbolAndProjectId> .GetInstance(); // Now see if the symbols the compiler returned actually match the full pattern. foreach (var symbolAndProjectId in symbolAndProjectIds) { var symbol = symbolAndProjectId.Symbol; // 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 ? new PatternMatches(patternMatcher.GetMatches(GetSearchName(symbol))) : patternMatcher.GetMatches(GetSearchName(symbol), GetContainer(symbol)); if (matches.IsEmpty) { // Didn't actually match the full pattern, ignore it. continue; } result.Add(symbolAndProjectId); } return(result.ToImmutableAndFree()); } }
/// <summary> /// Find the symbols for declarations made in source with a matching name. /// </summary> public static async Task <IEnumerable <ISymbol> > FindSourceDeclarationsAsync( Solution solution, Func <string, bool> predicate, SymbolFilter filter, CancellationToken cancellationToken = default(CancellationToken)) { return(await FindSourceDeclarationsAsync( solution, SearchQuery.CreateCustom(predicate), filter, cancellationToken).ConfigureAwait(false)); }
/// <summary> /// Find the symbols for declarations made in source with a matching name. /// </summary> public static Task <IEnumerable <ISymbol> > FindSourceDeclarationsAsync(Project project, Func <string, bool> predicate, SymbolFilter filter, CancellationToken cancellationToken = default(CancellationToken)) { return(FindSourceDeclarationsAsync(project, SearchQuery.CreateCustom(predicate), filter, cancellationToken)); }