[FIR IDE] Make fir resolve phase volatile and remove locks

This commit is contained in:
Igor Yakovlev
2021-07-16 20:20:10 +02:00
parent 78e249c2d5
commit e1c8f302a4
37 changed files with 96 additions and 205 deletions
@@ -32,6 +32,7 @@ import kotlin.properties.Delegates
class FirJavaClass @FirImplementationDetail internal constructor(
override val source: FirSourceElement?,
override val moduleData: FirModuleData,
@Volatile
override var resolvePhase: FirResolvePhase,
override val name: Name,
override val annotations: MutableList<FirAnnotationCall>,
@@ -37,6 +37,7 @@ class FirJavaConstructor @FirImplementationDetail constructor(
override val typeParameters: MutableList<FirTypeParameterRef>,
annotationBuilder: () -> List<FirAnnotationCall>,
override var status: FirDeclarationStatus,
@Volatile
override var resolvePhase: FirResolvePhase,
override val dispatchReceiverType: ConeKotlinType?,
) : FirConstructor() {
@@ -36,6 +36,7 @@ class FirJavaField @FirImplementationDetail constructor(
override val moduleData: FirModuleData,
override val symbol: FirFieldSymbol,
override val name: Name,
@Volatile
override var resolvePhase: FirResolvePhase,
override var returnTypeRef: FirTypeRef,
override var status: FirDeclarationStatus,
@@ -50,6 +50,7 @@ import kotlin.properties.Delegates
class FirJavaMethod @FirImplementationDetail constructor(
override val source: FirSourceElement?,
override val moduleData: FirModuleData,
@Volatile
override var resolvePhase: FirResolvePhase,
override val attributes: FirDeclarationAttributes,
override var returnTypeRef: FirTypeRef,
@@ -30,6 +30,7 @@ import kotlin.contracts.contract
class FirJavaValueParameter @FirImplementationDetail constructor(
override val source: FirSourceElement?,
override val moduleData: FirModuleData,
@Volatile
override var resolvePhase: FirResolvePhase,
override val attributes: FirDeclarationAttributes,
override var returnTypeRef: FirTypeRef,
@@ -55,6 +55,7 @@ internal class FirAnonymousFunctionImpl(
override val typeParameters: MutableList<FirTypeParameter>,
override var typeRef: FirTypeRef,
) : FirAnonymousFunction() {
@Volatile
override var resolvePhase: FirResolvePhase = FirResolvePhase.DECLARATIONS
override var status: FirDeclarationStatus = FirResolvedDeclarationStatusImpl.DEFAULT_STATUS_FOR_STATUSLESS_DECLARATIONS
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.visitors.*
internal class FirAnonymousInitializerImpl(
override val source: FirSourceElement?,
override val moduleData: FirModuleData,
@Volatile
override var resolvePhase: FirResolvePhase,
override val origin: FirDeclarationOrigin,
override val attributes: FirDeclarationAttributes,
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.fir.visitors.*
internal class FirAnonymousObjectImpl(
override val source: FirSourceElement?,
override val moduleData: FirModuleData,
@Volatile
override var resolvePhase: FirResolvePhase,
override val origin: FirDeclarationOrigin,
override val attributes: FirDeclarationAttributes,
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.fir.visitors.*
internal class FirConstructorImpl(
override val source: FirSourceElement?,
override val moduleData: FirModuleData,
@Volatile
override var resolvePhase: FirResolvePhase,
override val origin: FirDeclarationOrigin,
override val attributes: FirDeclarationAttributes,
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.fir.visitors.*
internal class FirDefaultSetterValueParameter(
override val source: FirSourceElement?,
override val moduleData: FirModuleData,
@Volatile
override var resolvePhase: FirResolvePhase,
override val origin: FirDeclarationOrigin,
override val attributes: FirDeclarationAttributes,
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.fir.visitors.*
internal class FirEnumEntryImpl(
override val source: FirSourceElement?,
override val moduleData: FirModuleData,
@Volatile
override var resolvePhase: FirResolvePhase,
override val origin: FirDeclarationOrigin,
override val attributes: FirDeclarationAttributes,
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.fir.visitors.*
internal class FirErrorFunctionImpl(
override val source: FirSourceElement?,
override val moduleData: FirModuleData,
@Volatile
override var resolvePhase: FirResolvePhase,
override val origin: FirDeclarationOrigin,
override val attributes: FirDeclarationAttributes,
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.fir.visitors.*
internal class FirErrorPropertyImpl(
override val source: FirSourceElement?,
override val moduleData: FirModuleData,
@Volatile
override var resolvePhase: FirResolvePhase,
override val origin: FirDeclarationOrigin,
override val attributes: FirDeclarationAttributes,
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.fir.visitors.*
class FirFieldImpl @FirImplementationDetail constructor(
override val source: FirSourceElement?,
override val moduleData: FirModuleData,
@Volatile
override var resolvePhase: FirResolvePhase,
override val origin: FirDeclarationOrigin,
override val attributes: FirDeclarationAttributes,
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.fir.visitors.*
internal class FirFileImpl(
override val source: FirSourceElement?,
override val moduleData: FirModuleData,
@Volatile
override var resolvePhase: FirResolvePhase,
override val origin: FirDeclarationOrigin,
override val attributes: FirDeclarationAttributes,
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.fir.visitors.*
internal class FirPrimaryConstructor(
override val source: FirSourceElement?,
override val moduleData: FirModuleData,
@Volatile
override var resolvePhase: FirResolvePhase,
override val origin: FirDeclarationOrigin,
override val attributes: FirDeclarationAttributes,
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.fir.visitors.*
open class FirPropertyAccessorImpl @FirImplementationDetail constructor(
override val source: FirSourceElement?,
override val moduleData: FirModuleData,
@Volatile
override var resolvePhase: FirResolvePhase,
override val origin: FirDeclarationOrigin,
override val attributes: FirDeclarationAttributes,
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.fir.visitors.*
internal class FirPropertyImpl(
override val source: FirSourceElement?,
override val moduleData: FirModuleData,
@Volatile
override var resolvePhase: FirResolvePhase,
override val origin: FirDeclarationOrigin,
override val attributes: FirDeclarationAttributes,
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.fir.visitors.*
internal class FirRegularClassImpl(
override val source: FirSourceElement?,
override val moduleData: FirModuleData,
@Volatile
override var resolvePhase: FirResolvePhase,
override val origin: FirDeclarationOrigin,
override val attributes: FirDeclarationAttributes,
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.fir.visitors.*
internal class FirSimpleFunctionImpl(
override val source: FirSourceElement?,
override val moduleData: FirModuleData,
@Volatile
override var resolvePhase: FirResolvePhase,
override val origin: FirDeclarationOrigin,
override val attributes: FirDeclarationAttributes,
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.fir.visitors.*
internal class FirTypeAliasImpl(
override val source: FirSourceElement?,
override val moduleData: FirModuleData,
@Volatile
override var resolvePhase: FirResolvePhase,
override val origin: FirDeclarationOrigin,
override val attributes: FirDeclarationAttributes,
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.fir.visitors.*
internal class FirTypeParameterImpl(
override val source: FirSourceElement?,
override val moduleData: FirModuleData,
@Volatile
override var resolvePhase: FirResolvePhase,
override val origin: FirDeclarationOrigin,
override val attributes: FirDeclarationAttributes,
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.fir.visitors.*
internal class FirValueParameterImpl(
override val source: FirSourceElement?,
override val moduleData: FirModuleData,
@Volatile
override var resolvePhase: FirResolvePhase,
override val origin: FirDeclarationOrigin,
override val attributes: FirDeclarationAttributes,
@@ -73,7 +73,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
declaration.configure {
+symbolWithPackage("fir.symbols", "FirBasedSymbol", "out FirDeclaration")
+field("moduleData", firModuleDataType)
+field("resolvePhase", resolvePhaseType, withReplace = true).apply { isMutable = true }
+field("resolvePhase", resolvePhaseType, withReplace = true).apply { isMutable = true; isVolatile = true }
+field("origin", declarationOriginType)
+field("attributes", declarationAttributesType)
shouldBeAbstractClass()
@@ -11,6 +11,7 @@ sealed class Field : Importable {
abstract val name: String
open val arguments = mutableListOf<Importable>()
abstract val nullable: Boolean
abstract var isVolatile: Boolean
open var withReplace: Boolean = false
abstract val isFirType: Boolean
@@ -71,6 +72,7 @@ sealed class Field : Importable {
class FieldWithDefault(val origin: Field) : Field() {
override val name: String get() = origin.name
override val type: String get() = origin.type
override var isVolatile: Boolean = origin.isVolatile
override val nullable: Boolean get() = origin.nullable
override var withReplace: Boolean
get() = origin.withReplace
@@ -123,7 +125,8 @@ class SimpleField(
override val packageName: String?,
val customType: Importable? = null,
override val nullable: Boolean,
override var withReplace: Boolean
override var withReplace: Boolean,
override var isVolatile: Boolean = false
) : Field() {
override val isFirType: Boolean = false
override val fullQualifiedName: String?
@@ -138,7 +141,8 @@ class SimpleField(
packageName,
customType,
nullable,
withReplace
withReplace,
isVolatile
).apply {
withBindThis = this@SimpleField.withBindThis
}
@@ -150,7 +154,8 @@ class SimpleField(
newType.packageName,
customType,
nullable,
withReplace
withReplace,
isVolatile
).also {
it.withBindThis = withBindThis
updateFieldsInCopy(it)
@@ -170,6 +175,7 @@ class FirField(
}
override val type: String get() = element.type
override var isVolatile: Boolean = false
override val packageName: String? get() = element.packageName
override val isFirType: Boolean = true
@@ -202,6 +208,7 @@ class FieldList(
override val nullable: Boolean
get() = false
override var isVolatile: Boolean = false
override var isMutable: Boolean = true
override fun internalCopy(): Field {
@@ -37,7 +37,6 @@ fun Element.generateCode(generationPath: File): GeneratedFile {
fun SmartPrinter.printElement(element: Element) {
with(element) {
val isInterface = kind == Kind.Interface || kind == Kind.SealedInterface
fun abstract() {
if (!isInterface) {
print("abstract ")
@@ -6,10 +6,14 @@
package org.jetbrains.kotlin.fir.tree.generator.printer
import org.jetbrains.kotlin.fir.tree.generator.model.Field
import org.jetbrains.kotlin.fir.tree.generator.model.SimpleField
import org.jetbrains.kotlin.util.SmartPrinter
fun SmartPrinter.printField(field: Field, isImplementation: Boolean, override: Boolean, end: String) {
if (isImplementation && !field.isVal && field.isVolatile) {
println("@Volatile")
}
if (override) {
print("override ")
}
@@ -23,6 +27,9 @@ fun SmartPrinter.printField(field: Field, isImplementation: Boolean, override: B
}
fun SmartPrinter.printFieldWithDefaultInImplementation(field: Field) {
if (!field.isVal && field.isVolatile) {
println("@Volatile")
}
val defaultValue = field.defaultValueInImplementation
print("override ")
if (field.isVal) {
@@ -73,6 +73,7 @@ fun SmartPrinter.printImplementation(implementation: Implementation) {
}
println("(")
withIndent {
fieldsWithoutDefault.forEachIndexed { _, field ->
printField(field, isImplementation = true, override = true, end = ",")
}
@@ -89,6 +90,7 @@ fun SmartPrinter.printImplementation(implementation: Implementation) {
withIndent {
if (isInterface || isAbstract) {
allFields.forEach {
abstract()
printField(it, isImplementation = true, override = true, end = "")
}
@@ -25,18 +25,16 @@ internal class IdeFirPhaseManager(
symbol: FirBasedSymbol<*>,
requiredPhase: FirResolvePhase
) {
val fir = symbol.fir as FirDeclaration
val fir = symbol.fir
try {
if (fir.resolvePhase < requiredPhase) {
lazyDeclarationResolver.lazyResolveDeclaration(
firDeclarationToResolve = fir,
moduleFileCache = cache,
scopeSession = ScopeSession(),
toPhase = requiredPhase,
checkPCE = true,
skipLocalDeclaration = true,
)
}
lazyDeclarationResolver.lazyResolveDeclaration(
firDeclarationToResolve = fir,
moduleFileCache = cache,
scopeSession = ScopeSession(),
toPhase = requiredPhase,
checkPCE = true,
skipLocalDeclaration = true,
)
} catch (e: Throwable) {
sessionInvalidator.invalidate(fir.moduleData.session)
throw e
@@ -13,8 +13,6 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.idea.fir.low.level.api.annotations.InternalForInline
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCache
import org.jetbrains.kotlin.idea.fir.low.level.api.lazy.resolve.ResolveType
import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeSourcesSession
import org.jetbrains.kotlin.idea.fir.low.level.api.util.getElementTextInContext
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
@@ -50,20 +48,6 @@ abstract class FirModuleResolveState {
internal abstract fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<FirPsiDiagnostic>
internal inline fun <D : FirDeclaration, R> withLock(declaration: D, declarationLockType: DeclarationLockType, action: (D) -> R): R {
val originalDeclaration = (declaration as? FirCallableDeclaration)?.unwrapFakeOverrides() ?: declaration
val session = originalDeclaration.moduleData.session
return when {
originalDeclaration.origin == FirDeclarationOrigin.Source && session is FirIdeSourcesSession -> {
val cache = session.cache
val file = tryGetCachedFirFile(declaration, cache)
?: error("Fir file was not found for\n${declaration.render()}\n${(declaration.psi as? KtElement)?.getElementTextInContext()}")
cache.firFileLockProvider.withLock(file, declarationLockType) { action(declaration) }
}
else -> action(declaration)
}
}
@InternalForInline
abstract fun findSourceFirDeclaration(
ktDeclaration: KtDeclaration,
@@ -125,7 +125,7 @@ fun <D : FirDeclaration, R> D.withFirDeclaration(
action: (D) -> R,
): R {
resolvedFirToPhase(phase, resolveState)
return resolveState.withLock(this, DeclarationLockType.READ_LOCK, action)
return action(this)
}
/**
@@ -138,31 +138,7 @@ fun <D : FirDeclaration, R> D.withFirDeclaration(
action: (D) -> R,
): R {
resolvedFirToType(type, resolveState)
return resolveState.withLock(this, DeclarationLockType.READ_LOCK, action)
}
/**
* Executes [action] with given [FirDeclaration] under write lock, so resolve **is possible** inside [action]
*/
fun <D : FirDeclaration, R> D.withFirDeclarationInWriteLock(
resolveState: FirModuleResolveState,
phase: FirResolvePhase = FirResolvePhase.RAW_FIR,
action: (D) -> R,
): R {
resolvedFirToPhase(phase, resolveState)
return resolveState.withLock(this, DeclarationLockType.WRITE_LOCK, action)
}
/**
* Executes [action] with given [FirDeclaration] under write lock, so resolve **is possible** inside [action]
*/
fun <D : FirDeclaration, R> D.withFirDeclarationInWriteLock(
resolveState: FirModuleResolveState,
resolveType: ResolveType = ResolveType.BodyResolveWithChildren,
action: (D) -> R,
): R {
resolvedFirToType(resolveType, resolveState)
return resolveState.withLock(this, DeclarationLockType.WRITE_LOCK, action)
return action(this)
}
/**
@@ -8,66 +8,24 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.file.builder
import com.google.common.collect.MapMaker
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.idea.fir.low.level.api.annotations.PrivateForInline
import org.jetbrains.kotlin.idea.fir.low.level.api.api.DeclarationLockType
import org.jetbrains.kotlin.idea.fir.low.level.api.util.lockWithPCECheck
import java.util.concurrent.ConcurrentMap
import java.util.concurrent.locks.ReadWriteLock
import java.util.concurrent.locks.ReentrantReadWriteLock
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
internal class LockProvider<KEY> {
private val locks: ConcurrentMap<KEY, ReadWriteLock> = MapMaker().weakKeys().makeMap()
@OptIn(PrivateForInline::class)
private val deadLockGuard = DeadLockGuard()
private val locks: ConcurrentMap<KEY, ReentrantLock> = MapMaker().weakKeys().makeMap()
@Suppress("NOTHING_TO_INLINE")
private inline fun getLockFor(key: KEY) = locks.getOrPut(key) { ReentrantReadWriteLock() }
private inline fun getLockFor(key: KEY) = locks.getOrPut(key) { ReentrantLock() }
@OptIn(PrivateForInline::class)
inline fun <R> withReadLock(key: KEY, action: () -> R): R {
val readLock = getLockFor(key).readLock()
return deadLockGuard.guardReadLock { readLock.withLock { action() } }
}
inline fun <R> withWriteLock(key: KEY, action: () -> R): R =
getLockFor(key).withLock(action)
@OptIn(PrivateForInline::class)
inline fun <R> withWriteLock(key: KEY, action: () -> R): R {
val writeLock = getLockFor(key).writeLock()
return deadLockGuard.guardWriteLock { writeLock.withLock { action() } }
}
@OptIn(PrivateForInline::class)
inline fun <R> withWriteLockPCECheck(key: KEY, lockingIntervalMs: Long, action: () -> R): R {
val writeLock = getLockFor(key).writeLock()
return deadLockGuard.guardWriteLock { writeLock.lockWithPCECheck(lockingIntervalMs, action) }
}
inline fun <R> withLock(declaration: KEY, declarationLockType: DeclarationLockType, action: () -> R): R = when (declarationLockType) {
DeclarationLockType.READ_LOCK -> withReadLock(declaration, action)
DeclarationLockType.WRITE_LOCK -> withWriteLock(declaration, action)
}
}
@PrivateForInline
internal class DeadLockGuard {
private val readLocksCount = ThreadLocal.withInitial { 0 }
inline fun <R> guardReadLock(action: () -> R): R {
readLocksCount.set(readLocksCount.get() + 1)
return try {
action()
} finally {
readLocksCount.set(readLocksCount.get() - 1)
}
}
inline fun <R> guardWriteLock(action: () -> R): R {
if (readLocksCount.get() > 0) {
throw ReadWriteDeadLockException()
}
return action()
}
inline fun <R> withWriteLockPCECheck(key: KEY, lockingIntervalMs: Long, action: () -> R): R =
getLockFor(key).lockWithPCECheck(lockingIntervalMs, action)
}
/**
@@ -83,6 +41,4 @@ internal inline fun <R> LockProvider<FirFile>.runCustomResolveUnderLock(
} else {
withWriteLock(key = firFile, action = body)
}
}
class ReadWriteDeadLockException : IllegalStateException("Acquiring write lock when read lock hold")
}
@@ -50,12 +50,6 @@ internal abstract class ModuleFileCache {
abstract fun getCachedFirFile(ktFile: KtFile): FirFile?
abstract val firFileLockProvider: LockProvider<FirFile>
inline fun <D : FirDeclaration, R> withReadLockOn(declaration: D, action: (D) -> R): R {
val file = getContainerFirFile(declaration)
?: error("No fir file found for\n${declaration.render()}")
return firFileLockProvider.withReadLock(file) { action(declaration) }
}
}
internal class ModuleFileCacheImpl(override val session: FirSession) : ModuleFileCache() {
@@ -123,9 +123,10 @@ internal class FileStructure private constructor(
toPhase = FirResolvePhase.BODY_RESOLVE,
checkPCE = true,
)
return moduleFileCache.firFileLockProvider.withReadLock(firFile) {
FileElementFactory.createFileStructureElement(firDeclaration, declaration, firFile, moduleFileCache.firFileLockProvider)
}
return FileElementFactory.createFileStructureElement(firDeclaration, declaration, firFile, moduleFileCache.firFileLockProvider)
// return moduleFileCache.firFileLockProvider.withReadLock(firFile) {
// FileElementFactory.createFileStructureElement(firDeclaration, declaration, firFile, moduleFileCache.firFileLockProvider)
// }
}
private fun createStructureElement(container: KtAnnotated): FileStructureElement = when (container) {
@@ -41,40 +41,26 @@ internal fun FirLazyDeclarationResolver.lazyResolveDeclaration(
require(firDeclaration is FirCallableDeclaration) {
"CallableReturnType type cannot be applied to ${firDeclaration::class.qualifiedName}"
}
//Need to be sync
if (firDeclaration.returnTypeRef is FirResolvedTypeRef) return
val containingFile = firDeclaration.getContainingFile()
if (containingFile != null) {
moduleFileCache.firFileLockProvider.runCustomResolveUnderLock(containingFile, checkPCE) {
if (firDeclaration.returnTypeRef !is FirResolvedTypeRef) {
lazyResolveDeclaration(
firDeclarationToResolve = firDeclaration,
moduleFileCache = moduleFileCache,
toPhase = FirResolvePhase.TYPES,
scopeSession = scopeSession,
checkPCE = checkPCE,
)
}
if (firDeclaration.returnTypeRef !is FirResolvedTypeRef) {
lazyResolveDeclaration(
firDeclarationToResolve = firDeclaration,
moduleFileCache = moduleFileCache,
toPhase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE,
scopeSession = scopeSession,
checkPCE = checkPCE,
)
}
check(firDeclaration.returnTypeRef is FirResolvedTypeRef)
}
} else {
if (firDeclaration.resolvePhase < FirResolvePhase.TYPES) {
lazyResolveDeclaration(
firDeclarationToResolve = firDeclaration,
moduleFileCache = moduleFileCache,
toPhase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE,
toPhase = FirResolvePhase.TYPES,
scopeSession = scopeSession,
checkPCE = checkPCE,
)
}
if (firDeclaration.returnTypeRef is FirResolvedTypeRef) return
lazyResolveDeclaration(
firDeclarationToResolve = firDeclaration,
moduleFileCache = moduleFileCache,
toPhase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE,
scopeSession = scopeSession,
checkPCE = checkPCE,
)
check(firDeclaration.returnTypeRef is FirResolvedTypeRef)
}
ResolveType.BodyResolveWithChildren, ResolveType.CallableBodyResolve -> {
require(firDeclaration is FirCallableDeclaration || toResolveType != ResolveType.CallableBodyResolve) {
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirAnnotationResolveStatus
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.FirImportResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
@@ -41,6 +42,7 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
checkPCE: Boolean,
collector: FirTowerDataContextCollector? = null,
) {
if (firFile.resolvePhase >= FirResolvePhase.IMPORTS) return
moduleFileCache.firFileLockProvider.runCustomResolveUnderLock(firFile, checkPCE) {
resolveFileAnnotationsWithoutLock(
firFile = firFile,
@@ -63,6 +65,7 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
scopeSession: ScopeSession,
collector: FirTowerDataContextCollector? = null,
) {
if (firFile.resolvePhase >= FirResolvePhase.IMPORTS) return
lazyResolveFileDeclarationWithoutLock(
firFile = firFile,
moduleFileCache = moduleFileCache,
@@ -116,6 +119,8 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
scopeSession: ScopeSession,
checkPCE: Boolean = false,
) {
if (toPhase == FirResolvePhase.RAW_FIR) return
if (firFile.resolvePhase >= toPhase) return
moduleFileCache.firFileLockProvider.runCustomResolveUnderLock(firFile, checkPCE) {
lazyResolveFileDeclarationWithoutLock(
firFile = firFile,
@@ -136,8 +141,9 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
collector: FirTowerDataContextCollector? = null,
) {
if (toPhase == FirResolvePhase.RAW_FIR) return
if (firFile.resolvePhase >= toPhase) return
if (firFile.resolvePhase == FirResolvePhase.RAW_FIR) {
val resolvePhase = firFile.resolvePhase
if (resolvePhase >= toPhase) return
if (resolvePhase == FirResolvePhase.RAW_FIR) {
firFile.transform<FirElement, Any?>(FirImportResolveTransformer(firFile.moduleData.session), null)
firFile.replaceResolvePhase(FirResolvePhase.IMPORTS)
}
@@ -245,6 +251,7 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
}
if (firDeclarationToResolve.resolvePhase >= toPhase) return
moduleFileCache.firFileLockProvider.runCustomResolveUnderLock(designation.firFile, checkPCE) {
runLazyDesignatedResolveWithoutLock(
designation = designation,
@@ -263,7 +270,9 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
toPhase: FirResolvePhase,
checkPCE: Boolean,
) {
if (designation.declaration.resolvePhase >= toPhase) return
if (toPhase == FirResolvePhase.RAW_FIR) return
val declarationResolvePhase = designation.declaration.resolvePhase
if (declarationResolvePhase >= toPhase) return
if (designation.firFile.resolvePhase == FirResolvePhase.RAW_FIR) {
lazyResolveFileDeclarationWithoutLock(
@@ -275,7 +284,7 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
)
}
if (toPhase == FirResolvePhase.IMPORTS) return
var currentPhase = maxOf(designation.declaration.resolvePhase, FirResolvePhase.IMPORTS)
var currentPhase = maxOf(declarationResolvePhase, FirResolvePhase.IMPORTS)
while (currentPhase < toPhase) {
currentPhase = currentPhase.next
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
import org.jetbrains.kotlin.idea.fir.low.level.api.api.withFirDeclaration
import org.jetbrains.kotlin.idea.fir.low.level.api.api.withFirDeclarationInWriteLock
import org.jetbrains.kotlin.idea.fir.low.level.api.lazy.resolve.ResolveType
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
@@ -31,16 +30,7 @@ internal class FirRefWithValidityCheck<out D : FirDeclaration>(fir: D, resolveSt
?: throw EntityWasGarbageCollectedException("FirElement")
val resolveState = resolveStateWeakRef.get()
?: throw EntityWasGarbageCollectedException("FirModuleResolveState")
return when (phase) {
FirResolvePhase.BODY_RESOLVE -> {
/*
The BODY_RESOLVE phase is the maximum possible phase we can resolve our declaration to
So there is not need to run whole `action` under read lock
*/
action(fir.withFirDeclaration(resolveState, phase) { it })
}
else -> fir.withFirDeclaration(resolveState, phase) { action(it) }
}
return fir.withFirDeclaration(resolveState, phase) { action(it) }
}
/**
@@ -62,23 +52,7 @@ internal class FirRefWithValidityCheck<out D : FirDeclaration>(fir: D, resolveSt
inline fun <R> withFirWithPossibleResolveInside(
phase: FirResolvePhase = FirResolvePhase.RAW_FIR,
crossinline action: (fir: D) -> R
): R {
token.assertIsValidAndAccessible()
val fir = firWeakRef.get()
?: throw EntityWasGarbageCollectedException("FirElement")
val resolveState = resolveStateWeakRef.get()
?: throw EntityWasGarbageCollectedException("FirModuleResolveState")
return when (phase) {
FirResolvePhase.BODY_RESOLVE -> {
/*
The BODY_RESOLVE phase is the maximum possible phase we can resolve our declaration to
So there is not need to run whole `action` under write lock
*/
action(fir.withFirDeclarationInWriteLock(resolveState, phase) { it })
}
else -> fir.withFirDeclarationInWriteLock(resolveState, phase) { action(it) }
}
}
): R = withFir(phase, action)
/**
* Runs [action] with fir element with write action hold
@@ -87,23 +61,7 @@ internal class FirRefWithValidityCheck<out D : FirDeclaration>(fir: D, resolveSt
inline fun <R> withFirWithPossibleResolveInside(
resolveType: ResolveType = ResolveType.NoResolve,
crossinline action: (fir: D) -> R
): R {
token.assertIsValidAndAccessible()
val fir = firWeakRef.get()
?: throw EntityWasGarbageCollectedException("FirElement")
val resolveState = resolveStateWeakRef.get()
?: throw EntityWasGarbageCollectedException("FirModuleResolveState")
return when (resolveType) {
ResolveType.BodyResolveWithChildren -> {
/*
The ResolveType type is the maximum possible phase we can resolve our declaration to
So there is not need to run whole `action` under write lock
*/
action(fir.withFirDeclarationInWriteLock(resolveState, resolveType) { it })
}
else -> fir.withFirDeclarationInWriteLock(resolveState, resolveType) { action(it) }
}
}
): R = withFir(resolveType, action)
val resolveState
get() = resolveStateWeakRef.get() ?: throw EntityWasGarbageCollectedException("FirModuleResolveState")
@@ -119,16 +77,7 @@ internal class FirRefWithValidityCheck<out D : FirDeclaration>(fir: D, resolveSt
?: throw EntityWasGarbageCollectedException("FirElement")
val resolveState = resolveStateWeakRef.get()
?: throw EntityWasGarbageCollectedException("FirModuleResolveState")
return when (type) {
ResolveType.BodyResolveWithChildren -> {
/*
The CallableBodyResolve type is the maximum possible phase we can resolve our declaration to
So there is not need to run whole `action` under read lock
*/
action(fir.withFirDeclaration(type, resolveState) { it })
}
else -> fir.withFirDeclaration(type, resolveState) { action(it) }
}
return fir.withFirDeclaration(type, resolveState) { action(it) }
}
inline fun <R> withFirAndCache(type: ResolveType, crossinline createValue: (fir: D) -> R) =