[FIR IDE] Fix IDE return type calculators

This commit is contained in:
Igor Yakovlev
2021-07-21 16:22:39 +02:00
parent 4711577b17
commit 66fa624ab7
9 changed files with 129 additions and 31 deletions
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.buildReturnExpression import org.jetbrains.kotlin.fir.expressions.builder.buildReturnExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildUnitExpression import org.jetbrains.kotlin.fir.expressions.builder.buildUnitExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirLazyBlock
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
@@ -881,5 +882,5 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
get() = initializer?.typeRef is FirResolvedTypeRef get() = initializer?.typeRef is FirResolvedTypeRef
private val FirFunction.bodyResolved: Boolean private val FirFunction.bodyResolved: Boolean
get() = body?.typeRef is FirResolvedTypeRef get() = body !is FirLazyBlock && body?.typeRef is FirResolvedTypeRef
} }
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.SessionHolder import org.jetbrains.kotlin.fir.resolve.SessionHolder
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.ImplicitBodyResolveComputationSession import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.ImplicitBodyResolveComputationSession
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.createReturnTypeCalculatorForIDE import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.createReturnTypeCalculatorForIDE
import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirIdeDesignatedImpliciteTypesBodyResolveTransformerForReturnTypeCalculator
internal object PersistentCheckerContextFactory { internal object PersistentCheckerContextFactory {
fun createEmptyPersistenceCheckerContext(sessionHolder: SessionHolder): PersistentCheckerContext { fun createEmptyPersistenceCheckerContext(sessionHolder: SessionHolder): PersistentCheckerContext {
@@ -18,7 +18,7 @@ internal object PersistentCheckerContextFactory {
sessionHolder.session, sessionHolder.session,
ScopeSession(), ScopeSession(),
ImplicitBodyResolveComputationSession(), ImplicitBodyResolveComputationSession(),
::FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator ::FirIdeDesignatedImpliciteTypesBodyResolveTransformerForReturnTypeCalculator
) )
return PersistentCheckerContext(sessionHolder, returnTypeCalculator) return PersistentCheckerContext(sessionHolder, returnTypeCalculator)
} }
@@ -7,32 +7,32 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.element.builder
import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.BodyResolveContext import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.BodyResolveContext
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirDesignatedBodyResolveTransformerForReturnTypeCalculator import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirDesignatedBodyResolveTransformerForReturnTypeCalculator
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.ImplicitBodyResolveComputationSession import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.ImplicitBodyResolveComputationSession
import org.jetbrains.kotlin.fir.symbols.ensureResolved
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignation import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignation
import org.jetbrains.kotlin.idea.fir.low.level.api.lazy.resolve.FirLazyBodiesCalculator import org.jetbrains.kotlin.idea.fir.low.level.api.lazy.resolve.FirLazyBodiesCalculator
fun FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator( fun FirIdeDesignatedImpliciteTypesBodyResolveTransformerForReturnTypeCalculator(
designation: Iterator<FirElement>, designation: Iterator<FirElement>,
session: FirSession, session: FirSession,
scopeSession: ScopeSession, scopeSession: ScopeSession,
implicitBodyResolveComputationSession: ImplicitBodyResolveComputationSession, implicitBodyResolveComputationSession: ImplicitBodyResolveComputationSession,
returnTypeCalculator: ReturnTypeCalculator, returnTypeCalculator: ReturnTypeCalculator,
outerBodyResolveContext: BodyResolveContext?, outerBodyResolveContext: BodyResolveContext?,
): FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculatorImpl { ): FirDesignatedBodyResolveTransformerForReturnTypeCalculator {
val designationList = mutableListOf<FirElement>() val designationList = mutableListOf<FirElement>()
for (element in designation) { for (element in designation) {
designationList.add(element) designationList.add(element)
} }
require(designationList.isNotEmpty()) { "Designation should not be empty" }
return FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculatorImpl( return FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculatorImpl(
designationList, designationList,
@@ -44,8 +44,8 @@ fun FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator(
) )
} }
class FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculatorImpl( private class FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculatorImpl(
designation: List<FirElement>, private val designation: List<FirElement>,
session: FirSession, session: FirSession,
scopeSession: ScopeSession, scopeSession: ScopeSession,
implicitBodyResolveComputationSession: ImplicitBodyResolveComputationSession, implicitBodyResolveComputationSession: ImplicitBodyResolveComputationSession,
@@ -59,26 +59,34 @@ class FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculatorImpl(
returnTypeCalculator, returnTypeCalculator,
outerBodyResolveContext outerBodyResolveContext
) { ) {
private val declarationDesignation = designation.filterIsInstance<FirDeclaration>() private val targetDeclaration = designation.last()
private inline fun <D : FirCallableDeclaration> D.processCallable(body: (FirDeclarationDesignation) -> Unit) {
if (this !== targetDeclaration) return
ensureResolved(FirResolvePhase.TYPES)
if (returnTypeRef !is FirImplicitTypeRef) return
val declarationList = designation.filterIsInstance<FirDeclaration>()
check(declarationList.isNotEmpty()) { "Invalid empty declaration designation" }
body(FirDeclarationDesignation(declarationList.dropLast(1), this))
}
override fun transformSimpleFunction( override fun transformSimpleFunction(
simpleFunction: FirSimpleFunction, simpleFunction: FirSimpleFunction,
data: ResolutionMode data: ResolutionMode
): FirSimpleFunction { ): FirSimpleFunction {
val firDesignation = FirDeclarationDesignation(declarationDesignation, simpleFunction) simpleFunction.processCallable {
FirLazyBodiesCalculator.calculateLazyBodiesForFunction(firDesignation) FirLazyBodiesCalculator.calculateLazyBodiesForFunction(it)
}
return super.transformSimpleFunction(simpleFunction, data) return super.transformSimpleFunction(simpleFunction, data)
} }
override fun transformConstructor(constructor: FirConstructor, data: ResolutionMode): FirConstructor { override fun transformProperty(
val firDesignation = FirDeclarationDesignation(declarationDesignation, constructor) property: FirProperty,
FirLazyBodiesCalculator.calculateLazyBodyForSecondaryConstructor(firDesignation) data: ResolutionMode
return super.transformConstructor(constructor, data) ): FirProperty {
} property.processCallable {
FirLazyBodiesCalculator.calculateLazyBodyForProperty(it)
override fun transformProperty(property: FirProperty, data: ResolutionMode): FirProperty { }
val firDesignation = FirDeclarationDesignation(declarationDesignation, property)
FirLazyBodiesCalculator.calculateLazyBodyForProperty(firDesignation)
return super.transformProperty(property, data) return super.transformProperty(property, data)
} }
} }
@@ -0,0 +1,80 @@
/*
* Copyright 2010-2021 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.idea.fir.low.level.api.element.builder
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.BodyResolveContext
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirDesignatedBodyResolveTransformerForReturnTypeCalculator
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.ImplicitBodyResolveComputationSession
import org.jetbrains.kotlin.fir.symbols.ensureResolved
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
fun FirIdeEnsureBasedTransformerForReturnTypeCalculator(
designation: Iterator<FirElement>,
session: FirSession,
scopeSession: ScopeSession,
implicitBodyResolveComputationSession: ImplicitBodyResolveComputationSession,
returnTypeCalculator: ReturnTypeCalculator,
outerBodyResolveContext: BodyResolveContext?,
): FirDesignatedBodyResolveTransformerForReturnTypeCalculator {
val designationList = mutableListOf<FirElement>()
for (element in designation) {
designationList.add(element)
}
require(designationList.isNotEmpty()) { "Designation should not be empty" }
return FirIdeEnsureBasedTransformerForReturnTypeCalculatorImpl(
designationList,
session,
scopeSession,
implicitBodyResolveComputationSession,
returnTypeCalculator,
outerBodyResolveContext
)
}
private class FirIdeEnsureBasedTransformerForReturnTypeCalculatorImpl(
designation: List<FirElement>,
session: FirSession,
scopeSession: ScopeSession,
implicitBodyResolveComputationSession: ImplicitBodyResolveComputationSession,
returnTypeCalculator: ReturnTypeCalculator,
outerBodyResolveContext: BodyResolveContext?,
) : FirDesignatedBodyResolveTransformerForReturnTypeCalculator(
designation.iterator(),
session,
scopeSession,
implicitBodyResolveComputationSession,
returnTypeCalculator,
outerBodyResolveContext
) {
private val targetDeclaration = designation.last()
private fun <T : FirCallableDeclaration> T.ensuredReturnType() {
if (this !== targetDeclaration) return
ensureResolved(FirResolvePhase.TYPES)
if (returnTypeRef !is FirImplicitTypeRef) return
ensureResolved(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE)
}
override fun transformSimpleFunction(simpleFunction: FirSimpleFunction, data: ResolutionMode): FirSimpleFunction {
simpleFunction.ensuredReturnType()
return super.transformSimpleFunction(simpleFunction, data)
}
override fun transformProperty(property: FirProperty, data: ResolutionMode): FirProperty {
property.ensuredReturnType()
return super.transformProperty(property, data)
}
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.idea.fir.low.level.api.file.builder package org.jetbrains.kotlin.idea.fir.low.level.api.file.builder
import com.google.common.collect.MapMaker import com.google.common.collect.MapMaker
import com.google.common.util.concurrent.CycleDetectingLockFactory
import org.jetbrains.kotlin.fir.declarations.FirFile 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.annotations.PrivateForInline
import org.jetbrains.kotlin.idea.fir.low.level.api.util.lockWithPCECheck import org.jetbrains.kotlin.idea.fir.low.level.api.util.lockWithPCECheck
@@ -16,8 +17,16 @@ import kotlin.concurrent.withLock
internal class LockProvider<KEY> { internal class LockProvider<KEY> {
private val locks: ConcurrentMap<KEY, ReentrantLock> = MapMaker().weakKeys().makeMap() private val locks: ConcurrentMap<KEY, ReentrantLock> = MapMaker().weakKeys().makeMap()
@Suppress("UnstableApiUsage")
private val lockFactory = CycleDetectingLockFactory.newInstance(CycleDetectingLockFactory.Policies.THROW)
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
private inline fun getLockFor(key: KEY) = locks.getOrPut(key) { ReentrantLock() } private inline fun getLockFor(key: KEY) = locks.getOrPut(key) {
val file = key as FirFile
val name = "${file.packageDirective.packageFqName.asString()}.${file.name}"
@Suppress("UnstableApiUsage")
lockFactory.newReentrantLock(name)
}
@OptIn(PrivateForInline::class) @OptIn(PrivateForInline::class)
inline fun <R> withWriteLock(key: KEY, action: () -> R): R = inline fun <R> withWriteLock(key: KEY, action: () -> R): R =
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotationResolveStatus
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.FirImportResolveTransformer import org.jetbrains.kotlin.fir.resolve.transformers.FirImportResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
import org.jetbrains.kotlin.fir.symbols.impl.FirAccessorSymbol
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignationWithFile import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignationWithFile
import org.jetbrains.kotlin.idea.fir.low.level.api.api.collectDesignationWithFile import org.jetbrains.kotlin.idea.fir.low.level.api.api.collectDesignationWithFile
import org.jetbrains.kotlin.idea.fir.low.level.api.api.tryCollectDesignationWithFile import org.jetbrains.kotlin.idea.fir.low.level.api.api.tryCollectDesignationWithFile
@@ -16,7 +16,8 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.ImplicitBodyRe
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.createReturnTypeCalculatorForIDE import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.createReturnTypeCalculatorForIDE
import org.jetbrains.kotlin.idea.fir.low.level.api.FirPhaseRunner import org.jetbrains.kotlin.idea.fir.low.level.api.FirPhaseRunner
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignationWithFile import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignationWithFile
import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirIdeDesignatedImpliciteTypesBodyResolveTransformerForReturnTypeCalculator
import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirIdeEnsureBasedTransformerForReturnTypeCalculator
import org.jetbrains.kotlin.idea.fir.low.level.api.transformers.FirLazyTransformerForIDE.Companion.updatePhaseDeep import org.jetbrains.kotlin.idea.fir.low.level.api.transformers.FirLazyTransformerForIDE.Companion.updatePhaseDeep
import org.jetbrains.kotlin.idea.fir.low.level.api.util.ensurePhase import org.jetbrains.kotlin.idea.fir.low.level.api.util.ensurePhase
@@ -38,7 +39,7 @@ internal class FirDesignatedBodyResolveTransformerForIDE(
session, session,
scopeSession, scopeSession,
ImplicitBodyResolveComputationSession(), ImplicitBodyResolveComputationSession(),
::FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator ::FirIdeEnsureBasedTransformerForReturnTypeCalculator
), ),
firTowerDataContextCollector = towerDataContextCollector, firTowerDataContextCollector = towerDataContextCollector,
firProviderInterceptor = firProviderInterceptor, firProviderInterceptor = firProviderInterceptor,
@@ -16,7 +16,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.createReturnTy
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.idea.fir.low.level.api.FirPhaseRunner import org.jetbrains.kotlin.idea.fir.low.level.api.FirPhaseRunner
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignationWithFile import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignationWithFile
import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirIdeDesignatedImpliciteTypesBodyResolveTransformerForReturnTypeCalculator
import org.jetbrains.kotlin.idea.fir.low.level.api.transformers.FirLazyTransformerForIDE.Companion.updatePhaseDeep import org.jetbrains.kotlin.idea.fir.low.level.api.transformers.FirLazyTransformerForIDE.Companion.updatePhaseDeep
import org.jetbrains.kotlin.idea.fir.low.level.api.util.ensurePhase import org.jetbrains.kotlin.idea.fir.low.level.api.util.ensurePhase
@@ -40,7 +40,7 @@ internal class FirDesignatedImplicitTypesTransformerForIDE(
session, session,
scopeSession, scopeSession,
implicitBodyResolveComputationSession, implicitBodyResolveComputationSession,
::FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator ::FirIdeDesignatedImpliciteTypesBodyResolveTransformerForReturnTypeCalculator
) )
) { ) {
private val ideDeclarationTransformer = IDEDeclarationTransformer(designation) private val ideDeclarationTransformer = IDEDeclarationTransformer(designation)
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataCo
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.ImplicitBodyResolveComputationSession import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.ImplicitBodyResolveComputationSession
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.createReturnTypeCalculatorForIDE import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.createReturnTypeCalculatorForIDE
import org.jetbrains.kotlin.idea.fir.low.level.api.FirPhaseRunner import org.jetbrains.kotlin.idea.fir.low.level.api.FirPhaseRunner
import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirIdeDesignatedImpliciteTypesBodyResolveTransformerForReturnTypeCalculator
internal class FirFileAnnotationsResolveTransformer( internal class FirFileAnnotationsResolveTransformer(
private val firFile: FirFile, private val firFile: FirFile,
@@ -31,7 +31,7 @@ internal class FirFileAnnotationsResolveTransformer(
session, session,
scopeSession, scopeSession,
implicitBodyResolveComputationSession, implicitBodyResolveComputationSession,
::FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator ::FirIdeDesignatedImpliciteTypesBodyResolveTransformerForReturnTypeCalculator
), ),
firTowerDataContextCollector = firTowerDataContextCollector firTowerDataContextCollector = firTowerDataContextCollector
), FirLazyTransformerForIDE { ), FirLazyTransformerForIDE {