Example #1
0
        internal static async Task <ImmutableArray <ISymbol> > FindSymbolsAsync(
            Project project,
            SymbolFinderOptions options         = null,
            IFindSymbolsProgress progress       = null,
            CancellationToken cancellationToken = default)
        {
            Compilation compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

            INamedTypeSymbol generatedCodeAttribute = compilation.GetTypeByMetadataName("System.CodeDom.Compiler.GeneratedCodeAttribute");

            ImmutableArray <ISymbol> .Builder symbols = null;

            var namespaceOrTypeSymbols = new Stack <INamespaceOrTypeSymbol>();

            namespaceOrTypeSymbols.Push(compilation.Assembly.GlobalNamespace);

            while (namespaceOrTypeSymbols.Count > 0)
            {
                INamespaceOrTypeSymbol namespaceOrTypeSymbol = namespaceOrTypeSymbols.Pop();

                foreach (ISymbol symbol in namespaceOrTypeSymbol.GetMembers())
                {
                    SymbolKind kind = symbol.Kind;

                    if (kind == SymbolKind.Namespace)
                    {
                        var namespaceSymbol = (INamespaceSymbol)symbol;

                        SymbolFilterReason reason = options.GetReason(namespaceSymbol);

                        if (reason == SymbolFilterReason.None)
                        {
                            namespaceOrTypeSymbols.Push(namespaceSymbol);
                        }

                        continue;
                    }

                    bool isUnused = false;

                    if (!options.UnusedOnly ||
                        UnusedSymbolUtility.CanBeUnusedSymbol(symbol))
                    {
                        SymbolFilterReason reason = options.GetReason(symbol);

                        switch (reason)
                        {
                        case SymbolFilterReason.None:
                        {
                            if (options.IgnoreGeneratedCode &&
                                GeneratedCodeUtility.IsGeneratedCode(symbol, generatedCodeAttribute, MefWorkspaceServices.Default.GetService <ISyntaxFactsService>(compilation.Language).IsComment, cancellationToken))
                            {
                                continue;
                            }

                            if (options.UnusedOnly &&
                                !symbol.IsImplicitlyDeclared)
                            {
                                isUnused = await UnusedSymbolUtility.IsUnusedSymbolAsync(symbol, project.Solution, cancellationToken).ConfigureAwait(false);
                            }

                            if (!options.UnusedOnly ||
                                isUnused)
                            {
                                progress?.OnSymbolFound(symbol);

                                (symbols ?? (symbols = ImmutableArray.CreateBuilder <ISymbol>())).Add(symbol);
                            }

                            break;
                        }

                        case SymbolFilterReason.Visibility:
                        case SymbolFilterReason.WithoutAttibute:
                        case SymbolFilterReason.ImplicitlyDeclared:
                        {
                            continue;
                        }

                        case SymbolFilterReason.SymbolGroup:
                        case SymbolFilterReason.Ignored:
                        case SymbolFilterReason.WithAttibute:
                        case SymbolFilterReason.Other:
                        {
                            break;
                        }

                        default:
                        {
                            Debug.Fail(reason.ToString());
                            break;
                        }
                        }
                    }

                    if (!isUnused &&
                        kind == SymbolKind.NamedType)
                    {
                        namespaceOrTypeSymbols.Push((INamedTypeSymbol)symbol);
                    }
                }
            }

            return(symbols?.ToImmutableArray() ?? ImmutableArray <ISymbol> .Empty);
        }