[LL FIR] move in-block analysis declarations closer to service
^KT-61842
This commit is contained in:
-52
@@ -5,17 +5,12 @@
|
||||
|
||||
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.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
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isContractDescriptionCallPsiCheck
|
||||
|
||||
internal object FileElementFactory {
|
||||
fun createFileStructureElement(
|
||||
@@ -74,50 +69,3 @@ internal object FileElementFactory {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Covered by org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.AbstractInBlockModificationTest
|
||||
* on the compiler side and by
|
||||
* org.jetbrains.kotlin.idea.fir.analysis.providers.trackers.AbstractProjectWideOutOfBlockKotlinModificationTrackerTest
|
||||
* on the plugin part
|
||||
*
|
||||
* @return The declaration in which a change of the passed receiver parameter can be treated as in-block modification
|
||||
*/
|
||||
internal fun PsiElement.getNonLocalReanalyzableContainingDeclaration(): KtDeclaration? {
|
||||
return when (val declaration = getNonLocalContainingOrThisDeclaration()) {
|
||||
is KtNamedFunction -> declaration.takeIf { function ->
|
||||
function.isReanalyzableContainer() && isElementInsideBody(declaration = function, child = this)
|
||||
}
|
||||
|
||||
is KtPropertyAccessor -> declaration.takeIf { accessor ->
|
||||
accessor.isReanalyzableContainer() && isElementInsideBody(declaration = accessor, child = this)
|
||||
}
|
||||
|
||||
is KtProperty -> declaration.takeIf { property ->
|
||||
property.isReanalyzableContainer() && property.delegateExpressionOrInitializer?.isAncestor(this) == true
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun isElementInsideBody(declaration: KtDeclarationWithBody, child: PsiElement): Boolean {
|
||||
val body = declaration.bodyExpression ?: return false
|
||||
if (!body.isAncestor(child)) return false
|
||||
return !isInsideContract(body = body, child = child)
|
||||
}
|
||||
|
||||
private fun isInsideContract(body: KtExpression, child: PsiElement): Boolean {
|
||||
if (body !is KtBlockExpression) return false
|
||||
|
||||
val firstStatement = body.firstStatement ?: return false
|
||||
if (!firstStatement.isContractDescriptionCallPsiCheck()) return false
|
||||
return firstStatement.isAncestor(child)
|
||||
}
|
||||
|
||||
private fun KtNamedFunction.isReanalyzableContainer(): Boolean = hasBlockBody() || typeReference != null
|
||||
|
||||
private fun KtPropertyAccessor.isReanalyzableContainer(): Boolean = isSetter || hasBlockBody() || property.typeReference != null
|
||||
|
||||
private fun KtProperty.isReanalyzableContainer(): Boolean = typeReference != null && !hasDelegateExpressionOrInitializer()
|
||||
|
||||
|
||||
+55
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirInternals
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getFirResolveSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.resolveToFirSymbol
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLocalContainingOrThisDeclaration
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.LLFirDeclarationModificationService.ModificationType
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirResolvableModuleSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirResolvableSession
|
||||
@@ -27,9 +28,17 @@ import org.jetbrains.kotlin.analysis.providers.analysisMessageBus
|
||||
import org.jetbrains.kotlin.analysis.providers.topics.KotlinTopics.MODULE_OUT_OF_BLOCK_MODIFICATION
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.psi.KtAnnotated
|
||||
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||
import org.jetbrains.kotlin.psi.KtCodeFragment
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtDeclarationWithBody
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.psi.KtPropertyAccessor
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isContractDescriptionCallPsiCheck
|
||||
|
||||
/**
|
||||
* This service is responsible for processing incoming [PsiElement] changes to reflect them on FIR tree.
|
||||
@@ -221,3 +230,49 @@ private sealed class ChangeType {
|
||||
override fun hashCode(): Int = blockOwner.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Covered by org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.AbstractInBlockModificationTest
|
||||
* on the compiler side and by
|
||||
* org.jetbrains.kotlin.idea.fir.analysis.providers.trackers.AbstractProjectWideOutOfBlockKotlinModificationTrackerTest
|
||||
* on the plugin part
|
||||
*
|
||||
* @return The declaration in which a change of the passed receiver parameter can be treated as in-block modification
|
||||
*/
|
||||
internal fun PsiElement.getNonLocalReanalyzableContainingDeclaration(): KtDeclaration? {
|
||||
return when (val declaration = getNonLocalContainingOrThisDeclaration()) {
|
||||
is KtNamedFunction -> declaration.takeIf { function ->
|
||||
function.isReanalyzableContainer() && isElementInsideBody(declaration = function, child = this)
|
||||
}
|
||||
|
||||
is KtPropertyAccessor -> declaration.takeIf { accessor ->
|
||||
accessor.isReanalyzableContainer() && isElementInsideBody(declaration = accessor, child = this)
|
||||
}
|
||||
|
||||
is KtProperty -> declaration.takeIf { property ->
|
||||
property.isReanalyzableContainer() && property.delegateExpressionOrInitializer?.isAncestor(this) == true
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun isElementInsideBody(declaration: KtDeclarationWithBody, child: PsiElement): Boolean {
|
||||
val body = declaration.bodyExpression ?: return false
|
||||
if (!body.isAncestor(child)) return false
|
||||
return !isInsideContract(body = body, child = child)
|
||||
}
|
||||
|
||||
private fun isInsideContract(body: KtExpression, child: PsiElement): Boolean {
|
||||
if (body !is KtBlockExpression) return false
|
||||
|
||||
val firstStatement = body.firstStatement ?: return false
|
||||
if (!firstStatement.isContractDescriptionCallPsiCheck()) return false
|
||||
return firstStatement.isAncestor(child)
|
||||
}
|
||||
|
||||
private fun KtNamedFunction.isReanalyzableContainer(): Boolean = hasBlockBody() || typeReference != null
|
||||
|
||||
private fun KtPropertyAccessor.isReanalyzableContainer(): Boolean = isSetter || hasBlockBody() || property.typeReference != null
|
||||
|
||||
private fun KtProperty.isReanalyzableContainer(): Boolean = typeReference != null && !hasDelegateExpressionOrInitializer()
|
||||
|
||||
Reference in New Issue
Block a user