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;
        }
Exemple #4
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;
        }