private Task <StrongBox <ImmutableArray <DiagnosticData> > > DeserializeAsync(DiagnosticDataSerializer serializer, object documentOrProject, object key, string stateKey, CancellationToken cancellationToken) { // when VS is loading new solution, we will try to find out all diagnostics persisted from previous VS session. // in that situation, it is possible that we have a lot of deserialization returning empty result. previously we used to // return default(ImmutableArray) for such case, but it turns out async/await framework has allocation issues with returning // default(value type), so we are using StrongBox to return no data as null. async/await has optimization where it will return // cached empty task if given value is null for reference type. (see AsyncMethodBuilder.GetTaskForResult) // // right now, we can't use Nullable either, since it is not one of value type the async/await will reuse cached task. in future, // if they do, we can change it to return Nullable<ImmutableArray> // // after initial deserialization, we track actual document/project that actually have diagnostics so no data won't be a common // case. // check cache first if (InMemoryStorage.TryGetValue(_owner.Analyzer, (key, stateKey), out var entry) && serializer.Version == entry.Version) { if (entry.Diagnostics.Length == 0) { // if there is no result, use cached task return(s_emptyResultTaskCache); } return(Task.FromResult(new StrongBox <ImmutableArray <DiagnosticData> >(entry.Diagnostics))); } // try to deserialize it return(serializer.DeserializeAsync(documentOrProject, stateKey, cancellationToken)); }
private ValueTask <ImmutableArray <DiagnosticData> > DeserializeDiagnosticsAsync( IPersistentStorageService persistentService, DiagnosticDataSerializer serializer, Project project, TextDocument?document, object key, string stateKey, CancellationToken cancellationToken ) { Contract.ThrowIfFalse(document == null || document.Project == project); if ( InMemoryStorage.TryGetValue(_owner.Analyzer, (key, stateKey), out var entry) && serializer.Version == entry.Version ) { return(ValueTaskFactory.FromResult(entry.Diagnostics)); } return(serializer.DeserializeAsync( persistentService, project, document, stateKey, cancellationToken )); }
private async Task <ImmutableArray <DiagnosticData> > DeserializeAsync(DiagnosticDataSerializer serializer, object documentOrProject, object key, string stateKey, CancellationToken cancellationToken) { // check cache first CacheEntry entry; if (InMemoryStorage.TryGetValue(_owner.Analyzer, ValueTuple.Create(key, stateKey), out entry) && serializer.Version == entry.Version) { return(entry.Diagnostics); } // try to deserialize it return(await serializer.DeserializeAsync(documentOrProject, stateKey, cancellationToken).ConfigureAwait(false)); }