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); }
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); }
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); }
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); }
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); } }
/// <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); }