|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Concurrent;
using System.Collections.Immutable;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Diagnostics.EngineV2
{
internal partial class DiagnosticIncrementalAnalyzer
{
private static class InMemoryStorage
{
// the reason using nested map rather than having tuple as key is so that I dont have a gigantic map
private static readonly ConcurrentDictionary<DiagnosticAnalyzer, ConcurrentDictionary<(object key, string stateKey), CacheEntry>> s_map =
new(concurrencyLevel: 2, capacity: 10);
public static bool TryGetValue(DiagnosticAnalyzer analyzer, (object key, string stateKey) key, out CacheEntry entry)
{
AssertKey(key);
entry = default;
return s_map.TryGetValue(analyzer, out var analyzerMap) &&
analyzerMap.TryGetValue(key, out entry);
}
public static void Cache(DiagnosticAnalyzer analyzer, (object key, string stateKey) key, CacheEntry entry)
{
AssertKey(key);
// add new cache entry
var analyzerMap = s_map.GetOrAdd(analyzer, _ => new ConcurrentDictionary<(object key, string stateKey), CacheEntry>(concurrencyLevel: 2, capacity: 10));
analyzerMap[key] = entry;
}
public static void Remove(DiagnosticAnalyzer analyzer, (object key, string stateKey) key)
{
AssertKey(key);
// remove the entry
if (!s_map.TryGetValue(analyzer, out var analyzerMap))
{
return;
}
analyzerMap.TryRemove(key, out _);
if (analyzerMap.IsEmpty)
{
s_map.TryRemove(analyzer, out _);
}
}
public static void DropCache(DiagnosticAnalyzer analyzer)
{
// drop any cache related to given analyzer
s_map.TryRemove(analyzer, out _);
}
// make sure key is either documentId or projectId
private static void AssertKey((object key, string stateKey) key)
=> Contract.ThrowIfFalse(key.key is DocumentId or ProjectId);
}
// in memory cache entry
private readonly struct CacheEntry
{
public readonly VersionStamp Version;
public readonly ImmutableArray<DiagnosticData> Diagnostics;
public CacheEntry(VersionStamp version, ImmutableArray<DiagnosticData> diagnostics)
{
Version = version;
Diagnostics = diagnostics;
}
}
}
}
|