diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/caches/NullableCaffeineCache.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/caches/NullableCaffeineCache.kt new file mode 100644 index 00000000000..d4279ea21d2 --- /dev/null +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/caches/NullableCaffeineCache.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.low.level.api.fir.caches + +import com.github.benmanes.caffeine.cache.Cache +import com.github.benmanes.caffeine.cache.Caffeine +import org.jetbrains.kotlin.analysis.low.level.api.fir.fir.caches.NullValue +import org.jetbrains.kotlin.analysis.low.level.api.fir.fir.caches.nullValueToNull + +/** + * A wrapper around a Caffeine [Cache] which stores `null` values returned by the computation in the form of explicit [NullValue]s. On a + * conceptual level, this allows the cache to store failures so that future accesses to the same key don't recompute the same failure. + */ +internal class NullableCaffeineCache(configure: (Caffeine) -> Caffeine) { + private val cache: Cache = configure(Caffeine.newBuilder()).build() + + /** + * Returns the value for the given [key] if it's contained in the cache, or computes the value with [compute] and adds it to the cache. + */ + fun get(key: K, compute: (K) -> V?): V? = cache.get(key) { compute(it) ?: NullValue }?.nullValueToNull() +}