[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
|
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.KtFakeSourceElementKind
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
|
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.collectDesignationWithFile
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirClassWithSpecificMembersResolveTarget
|
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.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirPrimaryConstructor
|
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 {
|
internal object FileElementFactory {
|
||||||
fun createFileStructureElement(
|
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.getFirResolveSession
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile
|
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.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.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.LLFirResolvableModuleSession
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirResolvableSession
|
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.analysis.providers.topics.KotlinTopics.MODULE_OUT_OF_BLOCK_MODIFICATION
|
||||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
import org.jetbrains.kotlin.psi.KtAnnotated
|
import org.jetbrains.kotlin.psi.KtAnnotated
|
||||||
|
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||||
import org.jetbrains.kotlin.psi.KtCodeFragment
|
import org.jetbrains.kotlin.psi.KtCodeFragment
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
|
import org.jetbrains.kotlin.psi.KtDeclarationWithBody
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
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.
|
* 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()
|
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