[LL FIR] do not reanalyze non-top level properties with initializer
Treat changes inside non-top level property initializer as OOB It is OOB because CFG for a class depends on a property initializer, so we must rebuild CFG for the class Also, this commit makes the API more understandable ^KT-59687
This commit is contained in:
-13
@@ -36,7 +36,6 @@ import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isObjectLiteral
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||
|
||||
@@ -307,15 +306,3 @@ internal fun PsiElement.getNonLocalContainingOrThisDeclaration(predicate: (KtDec
|
||||
|
||||
return candidate
|
||||
}
|
||||
|
||||
@Suppress("unused") // Used in the IDE plugin
|
||||
fun PsiElement.getNonLocalContainingInBodyDeclarationWith(): KtDeclaration? =
|
||||
getNonLocalContainingOrThisDeclaration { declaration ->
|
||||
when (declaration) {
|
||||
is KtNamedFunction -> declaration.bodyExpression?.isAncestor(this) == true
|
||||
is KtProperty -> declaration.initializer?.isAncestor(this) == true ||
|
||||
declaration.getter?.bodyExpression?.isAncestor(this) == true ||
|
||||
declaration.setter?.bodyExpression?.isAncestor(this) == true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
+31
-17
@@ -5,18 +5,19 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirInternals
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirClassWithSpecificMembersResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLocalContainingOrThisDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirPrimaryConstructor
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||
|
||||
internal object FileElementFactory {
|
||||
/**
|
||||
* should be consistent with [isReanalyzableContainer]
|
||||
*/
|
||||
fun createFileStructureElement(
|
||||
firDeclaration: FirDeclaration,
|
||||
ktDeclaration: KtDeclaration,
|
||||
@@ -103,22 +104,35 @@ internal object FileElementFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* should be consistent with [createFileStructureElement]
|
||||
* @return The declaration in which a change of the passed receiver parameter can be treated as in-block modification
|
||||
*/
|
||||
//TODO make internal
|
||||
fun isReanalyzableContainer(
|
||||
ktDeclaration: KtDeclaration,
|
||||
): Boolean = when (ktDeclaration) {
|
||||
is KtNamedFunction -> ktDeclaration.isReanalyzableContainer()
|
||||
is KtProperty -> ktDeclaration.isReanalyzableContainer()
|
||||
else -> false
|
||||
@LLFirInternals
|
||||
@Suppress("unused") // Used in the IDE plugin
|
||||
fun PsiElement.getNonLocalReanalyzableContainingDeclaration(): KtDeclaration? {
|
||||
return when (val declaration = getNonLocalContainingOrThisDeclaration()) {
|
||||
is KtNamedFunction -> declaration.takeIf { function ->
|
||||
function.isReanalyzableContainer() && function.bodyExpression?.isAncestor(this) == true
|
||||
}
|
||||
|
||||
is KtPropertyAccessor -> declaration.takeIf { accessor ->
|
||||
accessor.isReanalyzableContainer() && accessor.bodyExpression?.isAncestor(this) == true
|
||||
}
|
||||
|
||||
is KtProperty -> declaration.takeIf { property ->
|
||||
property.isReanalyzableContainer() && property.delegateExpressionOrInitializer?.isAncestor(this) == true
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtNamedFunction.isReanalyzableContainer() =
|
||||
name != null && hasExplicitTypeOrUnit
|
||||
private fun KtNamedFunction.isReanalyzableContainer(): Boolean = name != null && (hasBlockBody() || typeReference != null)
|
||||
|
||||
private fun KtProperty.isReanalyzableContainer() =
|
||||
name != null && typeReference != null
|
||||
private fun KtPropertyAccessor.isReanalyzableContainer(): Boolean {
|
||||
val property = property
|
||||
return property.name != null && (hasBlockBody() || property.typeReference != null)
|
||||
}
|
||||
|
||||
private fun KtProperty.isReanalyzableContainer(): Boolean =
|
||||
name != null && typeReference != null && (isTopLevel || !hasDelegateExpressionOrInitializer())
|
||||
|
||||
private val KtNamedFunction.hasExplicitTypeOrUnit
|
||||
get() = hasBlockBody() || typeReference != null
|
||||
|
||||
@@ -7,5 +7,5 @@ class X {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
|
||||
val y = 42/* NonReanalyzableNonClassDeclarationStructureElement */
|
||||
|
||||
var z: Int = 15/* ReanalyzablePropertyStructureElement */
|
||||
var z: Int = 15/* NonReanalyzableNonClassDeclarationStructureElement */
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ var x: Int = 10/* ReanalyzablePropertyStructureElement */
|
||||
}
|
||||
|
||||
class X {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
var y: Int = 10/* ReanalyzablePropertyStructureElement */
|
||||
var y: Int = 10/* NonReanalyzableNonClassDeclarationStructureElement */
|
||||
get() = field
|
||||
set(value) {
|
||||
field = value
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
open class A
|
||||
(init: A.() -> Unit)/* NonReanalyzableNonClassDeclarationStructureElement */
|
||||
{/* NonReanalyzableClassDeclarationStructureElement */
|
||||
val prop: String = ""/* ReanalyzablePropertyStructureElement */
|
||||
val prop: String = ""/* NonReanalyzableNonClassDeclarationStructureElement */
|
||||
}
|
||||
|
||||
class B()/* NonReanalyzableNonClassDeclarationStructureElement */ : A()/* NonReanalyzableClassDeclarationStructureElement */
|
||||
|
||||
Reference in New Issue
Block a user