public async Task <ImmutableArray <CompletionItem> > GetTopLevelTypesAsync(
            Project project,
            SyntaxContext syntaxContext,
            bool isInternalsVisible,
            CancellationToken cancellationToken)
        {
            if (!project.SupportsCompilation)
            {
                throw new ArgumentException(nameof(project));
            }

            var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

            // Since we only need top level types from source, therefore we only care if source symbol checksum changes.
            var checksum = await SymbolTreeInfo.GetSourceSymbolsChecksumAsync(project, cancellationToken).ConfigureAwait(false);

            return(GetAccessibleTopLevelTypesWorker(
                       project.Id,
                       compilation.Assembly,
                       checksum,
                       syntaxContext,
                       isInternalsVisible,
                       CacheService.ProjectItemsCache,
                       cancellationToken));
        }
            public override async Task AnalyzeDocumentAsync(Document document, SyntaxNode bodyOpt, InvocationReasons reasons, CancellationToken cancellationToken)
            {
                if (!SupportAnalysis(document.Project))
                {
                    return;
                }

                if (bodyOpt != null)
                {
                    // This was a method body edit.  We can reuse the existing SymbolTreeInfo if
                    // we have one.  We can't just bail out here as the change in the document means
                    // we'll have a new checksum.  We need to get that new checksum so that our
                    // cached information is valid.
                    if (_projectToInfo.TryGetValue(document.Project.Id, out var cachedInfo))
                    {
                        var checksum = await SymbolTreeInfo.GetSourceSymbolsChecksumAsync(
                            document.Project, cancellationToken).ConfigureAwait(false);

                        var newInfo = cachedInfo.WithChecksum(checksum);
                        _projectToInfo.AddOrUpdate(document.Project.Id, newInfo, (_1, _2) => newInfo);
                        return;
                    }
                }

                await UpdateSymbolTreeInfoAsync(document.Project, cancellationToken).ConfigureAwait(false);
            }
Beispiel #3
0
            private async Task UpdateSourceSymbolTreeInfoAsync(
                Project project,
                CancellationToken cancellationToken
                )
            {
                var checksum = await SymbolTreeInfo
                               .GetSourceSymbolsChecksumAsync(project, cancellationToken)
                               .ConfigureAwait(false);

                if (
                    !_projectIdToInfo.TryGetValue(project.Id, out var projectInfo) ||
                    projectInfo.Checksum != checksum
                    )
                {
                    projectInfo = await SymbolTreeInfo
                                  .GetInfoForSourceAssemblyAsync(
                        project,
                        checksum,
                        loadOnly : false,
                        cancellationToken
                        )
                                  .ConfigureAwait(false);

                    Contract.ThrowIfNull(projectInfo);
                    Contract.ThrowIfTrue(
                        projectInfo.Checksum != checksum,
                        "If we computed a SymbolTreeInfo, then its checksum much match our checksum."
                        );

                    // Mark that we're up to date with this project.  Future calls with the same
                    // semantic version can bail out immediately.
                    _projectIdToInfo[project.Id] = projectInfo;
                }
            }
            public async Task <SymbolTreeInfo> TryGetSourceSymbolTreeInfoAsync(
                Project project,
                CancellationToken cancellationToken
                )
            {
                // See if the last value produced matches what the caller is asking for.  If so, return that.
                var checksum = await SymbolTreeInfo
                               .GetSourceSymbolsChecksumAsync(project, cancellationToken)
                               .ConfigureAwait(false);

                if (
                    _projectIdToInfo.TryGetValue(project.Id, out var projectInfo) &&
                    projectInfo.Checksum == checksum
                    )
                {
                    return(projectInfo);
                }

                // If we didn't have it in our cache, see if we can load it from disk.
                // Note: pass 'loadOnly' so we only attempt to load from disk, not to actually
                // try to create the index.
                var info = await SymbolTreeInfo
                           .GetInfoForSourceAssemblyAsync(
                    project,
                    checksum,
                    loadOnly : true,
                    cancellationToken
                    )
                           .ConfigureAwait(false);

                return(info);
            }
Beispiel #5
0
        private static async Task <CacheEntry?> GetCacheEntryAsync(
            Project project,
            bool loadOnly,
            IImportCompletionCacheService <CacheEntry, object> cacheService,
            CancellationToken cancellationToken
            )
        {
            // While we are caching data from SyntaxTreeInfo, all the things we cared about here are actually based on sources symbols.
            // So using source symbol checksum would suffice.
            var checksum = await SymbolTreeInfo
                           .GetSourceSymbolsChecksumAsync(project, cancellationToken)
                           .ConfigureAwait(false);

            // Cache miss, create all requested items.
            if (
                !cacheService.ProjectItemsCache.TryGetValue(project.Id, out var cacheEntry) ||
                cacheEntry.Checksum != checksum ||
                cacheEntry.Language != project.Language
                )
            {
                var syntaxFacts =
                    project.LanguageServices.GetRequiredService <ISyntaxFactsService>();
                var builder = new CacheEntry.Builder(
                    checksum,
                    project.Language,
                    syntaxFacts.StringComparer
                    );

                foreach (var document in project.Documents)
                {
                    // Don't look for extension methods in generated code.
                    if (document.State.Attributes.IsGenerated)
                    {
                        continue;
                    }

                    var info = await document
                               .GetSyntaxTreeIndexAsync(loadOnly, cancellationToken)
                               .ConfigureAwait(false);

                    if (info == null)
                    {
                        return(null);
                    }

                    if (info.ContainsExtensionMethod)
                    {
                        builder.AddItem(info);
                    }
                }

                cacheEntry = builder.ToCacheEntry();
                cacheService.ProjectItemsCache[project.Id] = cacheEntry;
            }

            return(cacheEntry);
        }
Beispiel #6
0
            public async Task <SymbolTreeInfo> TryGetSourceSymbolTreeInfoAsync(
                Project project, CancellationToken cancellationToken)
            {
                if (_projectToInfo.TryGetValue(project.Id, out var projectInfo) &&
                    projectInfo.Checksum == await SymbolTreeInfo.GetSourceSymbolsChecksumAsync(project, cancellationToken).ConfigureAwait(false))
                {
                    return(projectInfo);
                }

                return(null);
            }
Beispiel #7
0
            private async Task UpdateSourceSymbolTreeInfoAsync(Project project, CancellationToken cancellationToken)
            {
                var checksum = await SymbolTreeInfo.GetSourceSymbolsChecksumAsync(project, cancellationToken).ConfigureAwait(false);

                if (!_projectToInfo.TryGetValue(project.Id, out var projectInfo) ||
                    projectInfo.Checksum != checksum)
                {
                    projectInfo = await SymbolTreeInfo.GetInfoForSourceAssemblyAsync(
                        project, checksum, cancellationToken).ConfigureAwait(false);

                    // Mark that we're up to date with this project.  Future calls with the same
                    // semantic version can bail out immediately.
                    _projectToInfo.AddOrUpdate(project.Id, projectInfo, (_1, _2) => projectInfo);
                }
            }
Beispiel #8
0
        /// <summary>
        /// Get appropriate completion items for all the visible top level types from given project.
        /// This method is intended to be used for getting types from source only, so the project must support compilation.
        /// For getting types from PE, use <see cref="TryGetUpToDateCacheForPEReference"/>.
        /// </summary>
        private async Task <TypeImportCompletionCacheEntry> GetUpToDateCacheForProjectAsync(Project project, CancellationToken cancellationToken)
        {
            // Since we only need top level types from source, therefore we only care if source symbol checksum changes.
            var checksum = await SymbolTreeInfo.GetSourceSymbolsChecksumAsync(project, cancellationToken).ConfigureAwait(false);

            var compilation = await project.GetRequiredCompilationAsync(cancellationToken).ConfigureAwait(false);

            return(CreateCacheWorker(
                       project.Id,
                       compilation.Assembly,
                       checksum,
                       CacheService.ProjectItemsCache,
                       new EditorBrowsableInfo(compilation),
                       cancellationToken));
        }
            public async Task GetTopLevelTypesAsync(
                Project project,
                Action <TypeImportCompletionItemInfo> handleItem,
                CancellationToken cancellationToken)
            {
                if (!project.SupportsCompilation)
                {
                    throw new ArgumentException(nameof(project));
                }

                var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

                // Since we only need top level types from source, therefore we only care if source symbol checksum changes.
                var checksum = await SymbolTreeInfo.GetSourceSymbolsChecksumAsync(project, cancellationToken).ConfigureAwait(false);

                GetAccessibleTopLevelTypesWorker(
                    project.Id,
                    compilation.Assembly,
                    checksum,
                    handleItem,
                    _projectItemsCache,
                    cancellationToken);
            }