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));
 }
Ejemplo n.º 6
0
 /// <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));
 }