[FIR IDE] Refactor low level resolve state for completion
Rename refactorings Remove redundant methods and implementations Increase code-logic locality Removed redundant entities
This commit is contained in:
committed by
TeamCityServer
parent
aa13936cb2
commit
aaefe94763
-2
@@ -6,7 +6,6 @@
|
|||||||
package org.jetbrains.kotlin.idea.completion
|
package org.jetbrains.kotlin.idea.completion
|
||||||
|
|
||||||
import com.intellij.codeInsight.completion.*
|
import com.intellij.codeInsight.completion.*
|
||||||
import com.intellij.codeInsight.lookup.LookupElement
|
|
||||||
import com.intellij.patterns.PlatformPatterns
|
import com.intellij.patterns.PlatformPatterns
|
||||||
import com.intellij.patterns.PsiJavaPatterns
|
import com.intellij.patterns.PsiJavaPatterns
|
||||||
import com.intellij.util.ProcessingContext
|
import com.intellij.util.ProcessingContext
|
||||||
@@ -26,7 +25,6 @@ import org.jetbrains.kotlin.idea.frontend.api.scopes.KtCompositeScope
|
|||||||
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScope
|
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScope
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScopeNameFilter
|
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScopeNameFilter
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtNamedSymbol
|
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithVisibility
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithVisibility
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtClassType
|
import org.jetbrains.kotlin.idea.frontend.api.types.KtClassType
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||||
|
|||||||
+2
-5
@@ -8,16 +8,13 @@ package org.jetbrains.kotlin.idea.completion.context
|
|||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.analyse
|
import org.jetbrains.kotlin.idea.frontend.api.analyse
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.analyseInFakeAnalysisSession
|
import org.jetbrains.kotlin.idea.frontend.api.analyseInDependedAnalysisSession
|
||||||
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
|
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
|
||||||
import org.jetbrains.kotlin.idea.references.mainReference
|
import org.jetbrains.kotlin.idea.references.mainReference
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
import org.jetbrains.kotlin.psi.KtLabelReferenceExpression
|
import org.jetbrains.kotlin.psi.KtLabelReferenceExpression
|
||||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
|
import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
|
||||||
import kotlin.contracts.ExperimentalContracts
|
|
||||||
import kotlin.contracts.InvocationKind
|
|
||||||
import kotlin.contracts.contract
|
|
||||||
|
|
||||||
internal sealed class FirPositionCompletionContext {
|
internal sealed class FirPositionCompletionContext {
|
||||||
abstract val position: PsiElement
|
abstract val position: PsiElement
|
||||||
@@ -51,7 +48,7 @@ internal object FirPositionCompletionContextDetector {
|
|||||||
action: KtAnalysisSession.() -> Unit
|
action: KtAnalysisSession.() -> Unit
|
||||||
) {
|
) {
|
||||||
return when (positionContext) {
|
return when (positionContext) {
|
||||||
is FirNameReferencePositionContext -> analyseInFakeAnalysisSession(
|
is FirNameReferencePositionContext -> analyseInDependedAnalysisSession(
|
||||||
basicContext.originalKtFile,
|
basicContext.originalKtFile,
|
||||||
positionContext.nameExpression,
|
positionContext.nameExpression,
|
||||||
action
|
action
|
||||||
|
|||||||
+1
-1
@@ -47,7 +47,7 @@ abstract class KtAnalysisSession(final override val token: ValidityToken) : Vali
|
|||||||
|
|
||||||
override val analysisSession: KtAnalysisSession get() = this
|
override val analysisSession: KtAnalysisSession get() = this
|
||||||
|
|
||||||
abstract fun createContextDependentCopy(originalKtFile: KtFile, fakeKtElement: KtElement): KtAnalysisSession
|
abstract fun createContextDependentCopy(originalKtFile: KtFile, dependencyKtElement: KtElement): KtAnalysisSession
|
||||||
|
|
||||||
internal val smartCastProvider: KtSmartCastProvider get() = smartCastProviderImpl
|
internal val smartCastProvider: KtSmartCastProvider get() = smartCastProviderImpl
|
||||||
protected abstract val smartCastProviderImpl: KtSmartCastProvider
|
protected abstract val smartCastProviderImpl: KtSmartCastProvider
|
||||||
|
|||||||
+14
-6
@@ -36,10 +36,14 @@ abstract class KtAnalysisSessionProvider : Disposable {
|
|||||||
abstract fun getAnalysisSession(contextElement: KtElement, factory: ValidityTokenFactory): KtAnalysisSession
|
abstract fun getAnalysisSession(contextElement: KtElement, factory: ValidityTokenFactory): KtAnalysisSession
|
||||||
|
|
||||||
@InvalidWayOfUsingAnalysisSession
|
@InvalidWayOfUsingAnalysisSession
|
||||||
inline fun <R> analyseInFakeAnalysisSession(originalFile: KtFile, fakeExpresion: KtElement, action: KtAnalysisSession.() -> R): R {
|
inline fun <R> analyseInDependedAnalysisSession(
|
||||||
val fakeAnalysisSession = getAnalysisSession(originalFile, ReadActionConfinementValidityTokenFactory)
|
originalFile: KtFile,
|
||||||
.createContextDependentCopy(originalFile, fakeExpresion)
|
dependencyExpression: KtElement,
|
||||||
return analyse(fakeAnalysisSession, ReadActionConfinementValidityTokenFactory, action)
|
action: KtAnalysisSession.() -> R
|
||||||
|
): R {
|
||||||
|
val dependedAnalysisSession = getAnalysisSession(originalFile, ReadActionConfinementValidityTokenFactory)
|
||||||
|
.createContextDependentCopy(originalFile, dependencyExpression)
|
||||||
|
return analyse(dependedAnalysisSession, ReadActionConfinementValidityTokenFactory, action)
|
||||||
}
|
}
|
||||||
|
|
||||||
@InvalidWayOfUsingAnalysisSession
|
@InvalidWayOfUsingAnalysisSession
|
||||||
@@ -89,8 +93,12 @@ inline fun <R> analyseWithCustomToken(
|
|||||||
contextElement.project.service<KtAnalysisSessionProvider>().analyse(contextElement, tokenFactory, action)
|
contextElement.project.service<KtAnalysisSessionProvider>().analyse(contextElement, tokenFactory, action)
|
||||||
|
|
||||||
@OptIn(InvalidWayOfUsingAnalysisSession::class)
|
@OptIn(InvalidWayOfUsingAnalysisSession::class)
|
||||||
inline fun <R> analyseInFakeAnalysisSession(originalFile: KtFile, fakeExpresion: KtElement, action: KtAnalysisSession.() -> R): R =
|
inline fun <R> analyseInDependedAnalysisSession(
|
||||||
originalFile.project.service<KtAnalysisSessionProvider>().analyseInFakeAnalysisSession(originalFile, fakeExpresion, action)
|
originalFile: KtFile,
|
||||||
|
dependencyExpression: KtElement,
|
||||||
|
action: KtAnalysisSession.() -> R
|
||||||
|
): R =
|
||||||
|
originalFile.project.service<KtAnalysisSessionProvider>().analyseInDependedAnalysisSession(originalFile, dependencyExpression, action)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute given [action] in [KtAnalysisSession] context like [analyse] does but execute it in read action
|
* Execute given [action] in [KtAnalysisSession] context like [analyse] does but execute it in read action
|
||||||
|
|||||||
+38
-49
@@ -6,7 +6,6 @@
|
|||||||
package org.jetbrains.kotlin.idea.fir.low.level.api
|
package org.jetbrains.kotlin.idea.fir.low.level.api
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
|
||||||
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.analysis.diagnostics.FirPsiDiagnostic
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
|
||||||
@@ -14,31 +13,34 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||||
import org.jetbrains.kotlin.fir.resolve.FirTowerDataContext
|
import org.jetbrains.kotlin.fir.resolve.FirTowerDataContext
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
|
|
||||||
import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo
|
import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.annotations.InternalForInline
|
import org.jetbrains.kotlin.idea.fir.low.level.api.annotations.InternalForInline
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.DiagnosticCheckerFilter
|
import org.jetbrains.kotlin.idea.fir.low.level.api.api.DiagnosticCheckerFilter
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
|
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
|
||||||
|
import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirTowerDataContextCollector
|
||||||
|
import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.getClosestAvailableParentContext
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCache
|
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCache
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.file.structure.FirElementsRecorder
|
import org.jetbrains.kotlin.idea.fir.low.level.api.file.structure.FirElementsRecorder
|
||||||
|
import org.jetbrains.kotlin.idea.fir.low.level.api.providers.firIdeProvider
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.util.containingKtFileIfAny
|
import org.jetbrains.kotlin.idea.fir.low.level.api.util.containingKtFileIfAny
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.util.originalKtFile
|
import org.jetbrains.kotlin.idea.fir.low.level.api.util.originalKtFile
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.components.KtDiagnosticCheckerFilter
|
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.KtLambdaExpression
|
import org.jetbrains.kotlin.psi.KtLambdaExpression
|
||||||
|
|
||||||
internal class FirModuleResolveStateForCompletion(
|
internal class FirModuleResolveStateDepended(
|
||||||
override val project: Project,
|
dependencyFirDeclaration: FirDeclaration,
|
||||||
private val originalState: FirModuleResolveStateImpl
|
originalFirFile: FirFile,
|
||||||
|
private val originalState: FirModuleResolveStateImpl,
|
||||||
) : FirModuleResolveState() {
|
) : FirModuleResolveState() {
|
||||||
override val moduleInfo: IdeaModuleInfo get() = originalState.moduleInfo
|
|
||||||
|
|
||||||
|
override val project: Project get() = originalState.project
|
||||||
|
override val moduleInfo: IdeaModuleInfo get() = originalState.moduleInfo
|
||||||
override val rootModuleSession get() = originalState.rootModuleSession
|
override val rootModuleSession get() = originalState.rootModuleSession
|
||||||
private val fileStructureCache = originalState.fileStructureCache
|
private val fileStructureCache = originalState.fileStructureCache
|
||||||
|
|
||||||
private val completionMapping = mutableMapOf<KtElement, FirElement>()
|
private val completionMapping = mutableMapOf<KtElement, FirElement>()
|
||||||
|
private val collector = FirTowerDataContextCollector()
|
||||||
|
|
||||||
override fun getSessionFor(moduleInfo: IdeaModuleInfo): FirSession =
|
override fun getSessionFor(moduleInfo: IdeaModuleInfo): FirSession =
|
||||||
originalState.getSessionFor(moduleInfo)
|
originalState.getSessionFor(moduleInfo)
|
||||||
@@ -57,24 +59,8 @@ internal class FirModuleResolveStateForCompletion(
|
|||||||
override fun getFirFile(ktFile: KtFile): FirFile =
|
override fun getFirFile(ktFile: KtFile): FirFile =
|
||||||
originalState.getFirFile(ktFile)
|
originalState.getFirFile(ktFile)
|
||||||
|
|
||||||
override fun isFirFileBuilt(ktFile: KtFile): Boolean {
|
override fun <D : FirDeclaration> resolvedFirToPhase(declaration: D, toPhase: FirResolvePhase): D =
|
||||||
error("Should not be called in in completion")
|
originalState.resolvedFirToPhase(declaration, toPhase)
|
||||||
}
|
|
||||||
|
|
||||||
override fun recordPsiToFirMappingsForCompletionFrom(fir: FirDeclaration, firFile: FirFile, ktFile: KtFile) {
|
|
||||||
synchronized(completionMapping) { fir.accept(FirElementsRecorder(), completionMapping) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun <D : FirDeclaration> resolvedFirToPhase(declaration: D, toPhase: FirResolvePhase): D {
|
|
||||||
return originalState.resolvedFirToPhase(declaration, toPhase)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun lazyResolveDeclarationForCompletion(
|
|
||||||
firDeclaration: FirDeclaration,
|
|
||||||
containerFirFile: FirFile,
|
|
||||||
) {
|
|
||||||
originalState.lazyResolveDeclarationForCompletion(firDeclaration, containerFirFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getFirFile(declaration: FirDeclaration, cache: ModuleFileCache): FirFile? {
|
override fun getFirFile(declaration: FirDeclaration, cache: ModuleFileCache): FirFile? {
|
||||||
val ktFile = declaration.containingKtFileIfAny ?: return null
|
val ktFile = declaration.containingKtFileIfAny ?: return null
|
||||||
@@ -83,34 +69,37 @@ internal class FirModuleResolveStateForCompletion(
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<FirPsiDiagnostic<*>> =
|
||||||
|
TODO("Diagnostics are not implemented for depended state")
|
||||||
|
|
||||||
override fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<FirPsiDiagnostic<*>> {
|
override fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<FirPsiDiagnostic<*>> =
|
||||||
error("Diagnostics should not be retrieved in completion")
|
TODO("Diagnostics are not implemented for depended state")
|
||||||
}
|
|
||||||
|
|
||||||
override fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<FirPsiDiagnostic<*>> {
|
|
||||||
error("Diagnostics should not be retrieved in completion")
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(InternalForInline::class)
|
@OptIn(InternalForInline::class)
|
||||||
override fun findNonLocalSourceFirDeclaration(ktDeclaration: KtDeclaration): FirDeclaration {
|
override fun findSourceFirDeclaration(ktDeclaration: KtLambdaExpression): FirDeclaration =
|
||||||
error("Should not be used in completion")
|
originalState.findSourceFirDeclaration(ktDeclaration)
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(InternalForInline::class)
|
@OptIn(InternalForInline::class)
|
||||||
override fun findSourceFirDeclaration(ktDeclaration: KtDeclaration): FirDeclaration {
|
override fun findSourceFirDeclaration(ktDeclaration: KtDeclaration): FirDeclaration =
|
||||||
return originalState.findSourceFirDeclaration(ktDeclaration)
|
originalState.findSourceFirDeclaration(ktDeclaration)
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(InternalForInline::class)
|
|
||||||
override fun findSourceFirDeclaration(ktDeclaration: KtLambdaExpression): FirDeclaration {
|
|
||||||
error("Should not be used in completion")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getBuiltFirFileOrNull(ktFile: KtFile): FirFile? {
|
|
||||||
error("Should not be used in completion")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getTowerDataContextForElement(element: KtElement): FirTowerDataContext? =
|
override fun getTowerDataContextForElement(element: KtElement): FirTowerDataContext? =
|
||||||
originalState.getTowerDataContextForElement(element)
|
collector.getClosestAvailableParentContext(element) ?: originalState.getTowerDataContextForElement(element)
|
||||||
|
|
||||||
|
init {
|
||||||
|
originalState.firFileBuilder.runCustomResolveWithPCECheck(originalFirFile, rootModuleSession.cache) {
|
||||||
|
originalState.firLazyDeclarationResolver.runLazyResolveWithoutLock(
|
||||||
|
dependencyFirDeclaration,
|
||||||
|
rootModuleSession.cache,
|
||||||
|
originalFirFile,
|
||||||
|
originalFirFile.session.firIdeProvider,
|
||||||
|
fromPhase = dependencyFirDeclaration.resolvePhase,
|
||||||
|
toPhase = FirResolvePhase.BODY_RESOLVE,
|
||||||
|
towerDataContextCollector = collector,
|
||||||
|
checkPCE = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized(completionMapping) { dependencyFirDeclaration.accept(FirElementsRecorder(), completionMapping) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+13
-45
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.idea.fir.low.level.api
|
package org.jetbrains.kotlin.idea.fir.low.level.api
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import org.jetbrains.annotations.TestOnly
|
||||||
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.analysis.diagnostics.FirPsiDiagnostic
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
|
||||||
@@ -74,24 +75,12 @@ internal class FirModuleResolveStateImpl(
|
|||||||
override fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<FirPsiDiagnostic<*>> =
|
override fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<FirPsiDiagnostic<*>> =
|
||||||
diagnosticsCollector.collectDiagnosticsForFile(ktFile, filter)
|
diagnosticsCollector.collectDiagnosticsForFile(ktFile, filter)
|
||||||
|
|
||||||
override fun getBuiltFirFileOrNull(ktFile: KtFile): FirFile? {
|
@TestOnly
|
||||||
|
internal fun getBuiltFirFileOrNull(ktFile: KtFile): FirFile? {
|
||||||
val cache = sessionProvider.getModuleCache(ktFile.getModuleInfo() as ModuleSourceInfo)
|
val cache = sessionProvider.getModuleCache(ktFile.getModuleInfo() as ModuleSourceInfo)
|
||||||
return firFileBuilder.getBuiltFirFileOrNull(ktFile, cache)
|
return firFileBuilder.getBuiltFirFileOrNull(ktFile, cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun recordPsiToFirMappingsForCompletionFrom(fir: FirDeclaration, firFile: FirFile, ktFile: KtFile) {
|
|
||||||
error("Should be called only from FirModuleResolveStateForCompletion")
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(InternalForInline::class)
|
|
||||||
override fun findNonLocalSourceFirDeclaration(
|
|
||||||
ktDeclaration: KtDeclaration,
|
|
||||||
): FirDeclaration = ktDeclaration.findSourceNonLocalFirDeclaration(
|
|
||||||
firFileBuilder,
|
|
||||||
rootModuleSession.firIdeProvider.symbolProvider,
|
|
||||||
sessionProvider.getModuleCache(ktDeclaration.getModuleInfo() as ModuleSourceInfo)
|
|
||||||
)
|
|
||||||
|
|
||||||
@OptIn(InternalForInline::class)
|
@OptIn(InternalForInline::class)
|
||||||
override fun findSourceFirDeclaration(ktDeclaration: KtDeclaration): FirDeclaration =
|
override fun findSourceFirDeclaration(ktDeclaration: KtDeclaration): FirDeclaration =
|
||||||
findSourceFirDeclarationByExpression(ktDeclaration)
|
findSourceFirDeclarationByExpression(ktDeclaration)
|
||||||
@@ -104,25 +93,28 @@ internal class FirModuleResolveStateImpl(
|
|||||||
* [ktDeclaration] should be either [KtDeclaration] or [KtLambdaExpression]
|
* [ktDeclaration] should be either [KtDeclaration] or [KtLambdaExpression]
|
||||||
*/
|
*/
|
||||||
private fun findSourceFirDeclarationByExpression(ktDeclaration: KtExpression): FirDeclaration {
|
private fun findSourceFirDeclarationByExpression(ktDeclaration: KtExpression): FirDeclaration {
|
||||||
val nonLocalFirDeclaration = ktDeclaration.getNonLocalContainingOrThisDeclaration()
|
val nonLocalNamedDeclaration = ktDeclaration.getNonLocalContainingOrThisDeclaration()
|
||||||
?: error("Declaration should have non-local container${ktDeclaration.getElementTextInContext()}")
|
?: error("Declaration should have non-local container${ktDeclaration.getElementTextInContext()}")
|
||||||
if (ktDeclaration == nonLocalFirDeclaration) return findNonLocalSourceFirDeclaration(ktDeclaration as KtDeclaration)
|
|
||||||
val container = nonLocalFirDeclaration.findSourceNonLocalFirDeclaration(
|
val nonLocalFirForNamedDeclaration = nonLocalNamedDeclaration.findSourceNonLocalFirDeclaration(
|
||||||
firFileBuilder,
|
firFileBuilder,
|
||||||
rootModuleSession.firIdeProvider.symbolProvider,
|
rootModuleSession.firIdeProvider.symbolProvider,
|
||||||
sessionProvider.getModuleCache(ktDeclaration.getModuleInfo() as ModuleSourceInfo)
|
sessionProvider.getModuleCache(ktDeclaration.getModuleInfo() as ModuleSourceInfo)
|
||||||
)
|
)
|
||||||
if (container.resolvePhase < FirResolvePhase.BODY_RESOLVE) {
|
|
||||||
val cache = (container.moduleData.session as FirIdeSourcesSession).cache
|
if (ktDeclaration == nonLocalNamedDeclaration) return nonLocalFirForNamedDeclaration
|
||||||
|
|
||||||
|
if (nonLocalFirForNamedDeclaration.resolvePhase < FirResolvePhase.BODY_RESOLVE) {
|
||||||
|
val cache = (nonLocalFirForNamedDeclaration.moduleData.session as FirIdeSourcesSession).cache
|
||||||
firLazyDeclarationResolver.lazyResolveDeclaration(
|
firLazyDeclarationResolver.lazyResolveDeclaration(
|
||||||
container,
|
nonLocalFirForNamedDeclaration,
|
||||||
cache,
|
cache,
|
||||||
FirResolvePhase.BODY_RESOLVE,
|
FirResolvePhase.BODY_RESOLVE,
|
||||||
checkPCE = false, /*TODO*/
|
checkPCE = false, /*TODO*/
|
||||||
towerDataContextCollector = collector,
|
towerDataContextCollector = collector,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val firDeclaration = FirElementFinder.findElementIn<FirDeclaration>(container) { firDeclaration ->
|
val firDeclaration = FirElementFinder.findElementIn<FirDeclaration>(nonLocalFirForNamedDeclaration) { firDeclaration ->
|
||||||
when (val realPsi = firDeclaration.realPsi) {
|
when (val realPsi = firDeclaration.realPsi) {
|
||||||
is KtObjectLiteralExpression -> realPsi.objectDeclaration == ktDeclaration
|
is KtObjectLiteralExpression -> realPsi.objectDeclaration == ktDeclaration
|
||||||
is KtFunctionLiteral -> realPsi.parent == ktDeclaration
|
is KtFunctionLiteral -> realPsi.parent == ktDeclaration
|
||||||
@@ -133,12 +125,6 @@ internal class FirModuleResolveStateImpl(
|
|||||||
?: error("FirDeclaration was not found for\n${ktDeclaration.getElementTextInContext()}")
|
?: error("FirDeclaration was not found for\n${ktDeclaration.getElementTextInContext()}")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isFirFileBuilt(ktFile: KtFile): Boolean {
|
|
||||||
val moduleSourceInfo = ktFile.getModuleInfo() as? ModuleSourceInfo ?: return true
|
|
||||||
val cache = sessionProvider.getModuleCache(moduleSourceInfo)
|
|
||||||
return firFileBuilder.isFirFileBuilt(ktFile, cache)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun <D : FirDeclaration> resolvedFirToPhase(declaration: D, toPhase: FirResolvePhase): D {
|
override fun <D : FirDeclaration> resolvedFirToPhase(declaration: D, toPhase: FirResolvePhase): D {
|
||||||
val fileCache = when (val session = declaration.moduleData.session) {
|
val fileCache = when (val session = declaration.moduleData.session) {
|
||||||
is FirIdeSourcesSession -> session.cache
|
is FirIdeSourcesSession -> session.cache
|
||||||
@@ -154,24 +140,6 @@ internal class FirModuleResolveStateImpl(
|
|||||||
return declaration
|
return declaration
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun lazyResolveDeclarationForCompletion(
|
|
||||||
firDeclaration: FirDeclaration,
|
|
||||||
containerFirFile: FirFile,
|
|
||||||
) {
|
|
||||||
firFileBuilder.runCustomResolveWithPCECheck(containerFirFile, rootModuleSession.cache) {
|
|
||||||
firLazyDeclarationResolver.runLazyResolveWithoutLock(
|
|
||||||
firDeclaration,
|
|
||||||
rootModuleSession.cache,
|
|
||||||
containerFirFile,
|
|
||||||
containerFirFile.moduleData.session.firIdeProvider,
|
|
||||||
fromPhase = firDeclaration.resolvePhase,
|
|
||||||
toPhase = FirResolvePhase.BODY_RESOLVE,
|
|
||||||
towerDataContextCollector = collector,
|
|
||||||
checkPCE = true
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getFirFile(declaration: FirDeclaration, cache: ModuleFileCache): FirFile? =
|
override fun getFirFile(declaration: FirDeclaration, cache: ModuleFileCache): FirFile? =
|
||||||
cache.getContainerFirFile(declaration)
|
cache.getContainerFirFile(declaration)
|
||||||
|
|
||||||
|
|||||||
+13
-13
@@ -18,31 +18,31 @@ import org.jetbrains.kotlin.psi.*
|
|||||||
object DeclarationCopyBuilder {
|
object DeclarationCopyBuilder {
|
||||||
fun createDeclarationCopy(
|
fun createDeclarationCopy(
|
||||||
originalFirDeclaration: FirDeclaration,
|
originalFirDeclaration: FirDeclaration,
|
||||||
fakeKtDeclaration: KtDeclaration,
|
copiedKtDeclaration: KtDeclaration,
|
||||||
state: FirModuleResolveState,
|
state: FirModuleResolveState,
|
||||||
): FirDeclaration {
|
): FirDeclaration {
|
||||||
return when (fakeKtDeclaration) {
|
return when (copiedKtDeclaration) {
|
||||||
is KtNamedFunction -> createFunctionCopy(
|
is KtNamedFunction -> createFunctionCopy(
|
||||||
fakeKtDeclaration,
|
copiedKtDeclaration,
|
||||||
originalFirDeclaration as FirSimpleFunction,
|
originalFirDeclaration as FirSimpleFunction,
|
||||||
state
|
state
|
||||||
)
|
)
|
||||||
is KtProperty -> createPropertyCopy(
|
is KtProperty -> createPropertyCopy(
|
||||||
fakeKtDeclaration,
|
copiedKtDeclaration,
|
||||||
originalFirDeclaration as FirProperty,
|
originalFirDeclaration as FirProperty,
|
||||||
state
|
state
|
||||||
)
|
)
|
||||||
is KtClassOrObject -> createClassCopy(
|
is KtClassOrObject -> createClassCopy(
|
||||||
fakeKtDeclaration,
|
copiedKtDeclaration,
|
||||||
originalFirDeclaration as FirRegularClass,
|
originalFirDeclaration as FirRegularClass,
|
||||||
state
|
state
|
||||||
)
|
)
|
||||||
is KtTypeAlias -> createTypeAliasCopy(
|
is KtTypeAlias -> createTypeAliasCopy(
|
||||||
fakeKtDeclaration,
|
copiedKtDeclaration,
|
||||||
originalFirDeclaration as FirTypeAlias,
|
originalFirDeclaration as FirTypeAlias,
|
||||||
state
|
state
|
||||||
)
|
)
|
||||||
else -> error("Unsupported declaration ${fakeKtDeclaration::class.simpleName}")
|
else -> error("Unsupported declaration ${copiedKtDeclaration::class.simpleName}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,11 +64,11 @@ object DeclarationCopyBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createClassCopy(
|
private fun createClassCopy(
|
||||||
fakeKtClassOrObject: KtClassOrObject,
|
copiedKtClassOrObject: KtClassOrObject,
|
||||||
originalFirClass: FirRegularClass,
|
originalFirClass: FirRegularClass,
|
||||||
state: FirModuleResolveState,
|
state: FirModuleResolveState,
|
||||||
): FirRegularClass {
|
): FirRegularClass {
|
||||||
val builtClass = createCopy(fakeKtClassOrObject, originalFirClass)
|
val builtClass = createCopy(copiedKtClassOrObject, originalFirClass)
|
||||||
|
|
||||||
return buildRegularClassCopy(originalFirClass) {
|
return buildRegularClassCopy(originalFirClass) {
|
||||||
declarations.clear()
|
declarations.clear()
|
||||||
@@ -79,11 +79,11 @@ object DeclarationCopyBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createTypeAliasCopy(
|
private fun createTypeAliasCopy(
|
||||||
fakeKtTypeAlias: KtTypeAlias,
|
copiedKtTypeAlias: KtTypeAlias,
|
||||||
originalFirTypeAlias: FirTypeAlias,
|
originalFirTypeAlias: FirTypeAlias,
|
||||||
state: FirModuleResolveState,
|
state: FirModuleResolveState,
|
||||||
): FirTypeAlias {
|
): FirTypeAlias {
|
||||||
val builtTypeAlias = createCopy(fakeKtTypeAlias, originalFirTypeAlias)
|
val builtTypeAlias = createCopy(copiedKtTypeAlias, originalFirTypeAlias)
|
||||||
|
|
||||||
return buildTypeAliasCopy(originalFirTypeAlias) {
|
return buildTypeAliasCopy(originalFirTypeAlias) {
|
||||||
expandedTypeRef = builtTypeAlias.expandedTypeRef
|
expandedTypeRef = builtTypeAlias.expandedTypeRef
|
||||||
@@ -135,14 +135,14 @@ object DeclarationCopyBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal inline fun <reified T : FirDeclaration> createCopy(
|
internal inline fun <reified T : FirDeclaration> createCopy(
|
||||||
fakeKtDeclaration: KtDeclaration,
|
copiedKtDeclaration: KtDeclaration,
|
||||||
originalFirDeclaration: T,
|
originalFirDeclaration: T,
|
||||||
): T {
|
): T {
|
||||||
return RawFirFragmentForLazyBodiesBuilder.build(
|
return RawFirFragmentForLazyBodiesBuilder.build(
|
||||||
session = originalFirDeclaration.moduleData.session,
|
session = originalFirDeclaration.moduleData.session,
|
||||||
baseScopeProvider = originalFirDeclaration.moduleData.session.firIdeProvider.kotlinScopeProvider,
|
baseScopeProvider = originalFirDeclaration.moduleData.session.firIdeProvider.kotlinScopeProvider,
|
||||||
designation = originalFirDeclaration.collectDesignation().fullDesignation,
|
designation = originalFirDeclaration.collectDesignation().fullDesignation,
|
||||||
declaration = fakeKtDeclaration
|
declaration = copiedKtDeclaration
|
||||||
) as T
|
) as T
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-20
@@ -34,8 +34,6 @@ abstract class FirModuleResolveState {
|
|||||||
|
|
||||||
internal abstract fun getFirFile(ktFile: KtFile): FirFile
|
internal abstract fun getFirFile(ktFile: KtFile): FirFile
|
||||||
|
|
||||||
internal abstract fun isFirFileBuilt(ktFile: KtFile): Boolean
|
|
||||||
|
|
||||||
internal abstract fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<FirPsiDiagnostic<*>>
|
internal abstract fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<FirPsiDiagnostic<*>>
|
||||||
|
|
||||||
internal abstract fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<FirPsiDiagnostic<*>>
|
internal abstract fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<FirPsiDiagnostic<*>>
|
||||||
@@ -56,14 +54,6 @@ abstract class FirModuleResolveState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestOnly
|
|
||||||
internal abstract fun getBuiltFirFileOrNull(ktFile: KtFile): FirFile?
|
|
||||||
|
|
||||||
@InternalForInline
|
|
||||||
abstract fun findNonLocalSourceFirDeclaration(
|
|
||||||
ktDeclaration: KtDeclaration,
|
|
||||||
): FirDeclaration
|
|
||||||
|
|
||||||
@InternalForInline
|
@InternalForInline
|
||||||
abstract fun findSourceFirDeclaration(
|
abstract fun findSourceFirDeclaration(
|
||||||
ktDeclaration: KtDeclaration,
|
ktDeclaration: KtDeclaration,
|
||||||
@@ -74,18 +64,8 @@ abstract class FirModuleResolveState {
|
|||||||
ktDeclaration: KtLambdaExpression,
|
ktDeclaration: KtLambdaExpression,
|
||||||
): FirDeclaration
|
): FirDeclaration
|
||||||
|
|
||||||
|
|
||||||
// todo temporary, used only in completion
|
|
||||||
internal abstract fun recordPsiToFirMappingsForCompletionFrom(fir: FirDeclaration, firFile: FirFile, ktFile: KtFile)
|
|
||||||
|
|
||||||
internal abstract fun <D : FirDeclaration> resolvedFirToPhase(declaration: D, toPhase: FirResolvePhase): D
|
internal abstract fun <D : FirDeclaration> resolvedFirToPhase(declaration: D, toPhase: FirResolvePhase): D
|
||||||
|
|
||||||
// todo temporary, used only in completion
|
|
||||||
internal abstract fun lazyResolveDeclarationForCompletion(
|
|
||||||
firDeclaration: FirDeclaration,
|
|
||||||
containerFirFile: FirFile,
|
|
||||||
)
|
|
||||||
|
|
||||||
internal abstract fun getFirFile(declaration: FirDeclaration, cache: ModuleFileCache): FirFile?
|
internal abstract fun getFirFile(declaration: FirDeclaration, cache: ModuleFileCache): FirFile?
|
||||||
|
|
||||||
abstract fun getTowerDataContextForElement(element: KtElement): FirTowerDataContext?
|
abstract fun getTowerDataContextForElement(element: KtElement): FirTowerDataContext?
|
||||||
|
|||||||
-33
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.api
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveStateForCompletion
|
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveStateImpl
|
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
|
||||||
|
|
||||||
object LowLevelFirApiFacadeForCompletion {
|
|
||||||
fun getResolveStateForCompletion(originalState: FirModuleResolveState): FirModuleResolveState {
|
|
||||||
check(originalState is FirModuleResolveStateImpl)
|
|
||||||
return FirModuleResolveStateForCompletion(originalState.project, originalState)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun recordCompletionContextForDeclaration(
|
|
||||||
firFile: FirFile,
|
|
||||||
fakeKtDeclaration: KtDeclaration,
|
|
||||||
originalKtDeclaration: KtDeclaration,
|
|
||||||
fakeContainingFile: KtFile,
|
|
||||||
state: FirModuleResolveState,
|
|
||||||
) {
|
|
||||||
val originalFirDeclaration = originalKtDeclaration.getOrBuildFirOfType<FirDeclaration>(state)
|
|
||||||
val fakeFirDeclaration = DeclarationCopyBuilder.createDeclarationCopy(originalFirDeclaration, fakeKtDeclaration, state)
|
|
||||||
|
|
||||||
state.lazyResolveDeclarationForCompletion(fakeFirDeclaration, firFile)
|
|
||||||
state.recordPsiToFirMappingsForCompletionFrom(fakeFirDeclaration, firFile, fakeContainingFile)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+78
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* 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.api
|
||||||
|
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
import com.intellij.psi.util.parentsOfType
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveStateDepended
|
||||||
|
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveStateImpl
|
||||||
|
import org.jetbrains.kotlin.idea.fir.low.level.api.util.originalDeclaration
|
||||||
|
import org.jetbrains.kotlin.idea.util.getElementTextInContext
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||||
|
|
||||||
|
object LowLevelFirApiFacadeForDependentCopy {
|
||||||
|
|
||||||
|
private fun KtDeclaration.canBeEnclosingDeclaration(): Boolean = when (this) {
|
||||||
|
is KtNamedFunction -> isTopLevel || containingClassOrObject?.isLocal == false
|
||||||
|
is KtProperty -> isTopLevel || containingClassOrObject?.isLocal == false
|
||||||
|
is KtClassOrObject -> !isLocal
|
||||||
|
is KtTypeAlias -> isTopLevel() || containingClassOrObject?.isLocal == false
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findEnclosingNonLocalDeclaration(position: KtElement): KtNamedDeclaration? =
|
||||||
|
position.parentsOfType<KtNamedDeclaration>().firstOrNull { ktDeclaration ->
|
||||||
|
ktDeclaration.canBeEnclosingDeclaration()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T : KtElement> locateDeclarationInFileByOffset(offsetElement: T, file: KtFile): T? {
|
||||||
|
val elementOffset = offsetElement.textOffset
|
||||||
|
val elementAtOffset = file.findElementAt(elementOffset) ?: return null
|
||||||
|
return PsiTreeUtil.getParentOfType(elementAtOffset, offsetElement::class.java, false)?.takeIf { it.textOffset == elementOffset }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun recordOriginalDeclaration(targetDeclaration: KtNamedDeclaration, originalDeclaration: KtNamedDeclaration) {
|
||||||
|
require(!targetDeclaration.isPhysical)
|
||||||
|
require(originalDeclaration.containingKtFile !== targetDeclaration.containingKtFile)
|
||||||
|
val originalDeclrationParents = originalDeclaration.parentsOfType<KtDeclaration>().toList()
|
||||||
|
val fakeDeclarationParents = targetDeclaration.parentsOfType<KtDeclaration>().toList()
|
||||||
|
originalDeclrationParents.zip(fakeDeclarationParents) { original, fake ->
|
||||||
|
fake.originalDeclaration = original
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getResolveStateForDependedCopy(
|
||||||
|
originalState: FirModuleResolveState,
|
||||||
|
originalKtFile: KtFile,
|
||||||
|
dependencyKtElement: KtElement
|
||||||
|
): FirModuleResolveState {
|
||||||
|
require(originalState is FirModuleResolveStateImpl)
|
||||||
|
|
||||||
|
val dependencyNonLocalDeclaration = findEnclosingNonLocalDeclaration(dependencyKtElement)
|
||||||
|
?: error("Cannot find enclosing declaration for ${dependencyKtElement.getElementTextInContext()}")
|
||||||
|
|
||||||
|
val originalNonLocalDeclaration = locateDeclarationInFileByOffset(dependencyNonLocalDeclaration, originalKtFile)
|
||||||
|
?: error("Cannot find original function matching to ${dependencyNonLocalDeclaration.getElementTextInContext()} in $originalKtFile")
|
||||||
|
|
||||||
|
recordOriginalDeclaration(
|
||||||
|
targetDeclaration = dependencyNonLocalDeclaration,
|
||||||
|
originalDeclaration = originalNonLocalDeclaration
|
||||||
|
)
|
||||||
|
|
||||||
|
val originalFirDeclaration = originalNonLocalDeclaration.getOrBuildFirOfType<FirDeclaration>(originalState)
|
||||||
|
val copiedFirDeclaration = DeclarationCopyBuilder.createDeclarationCopy(
|
||||||
|
originalFirDeclaration = originalFirDeclaration,
|
||||||
|
copiedKtDeclaration = dependencyNonLocalDeclaration,
|
||||||
|
state = originalState
|
||||||
|
)
|
||||||
|
|
||||||
|
val originalFirFile = originalState.getFirFile(originalKtFile)
|
||||||
|
|
||||||
|
return FirModuleResolveStateDepended(copiedFirDeclaration, originalFirFile, originalState)
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
@@ -36,6 +36,7 @@ abstract class AbstractFirLazyDeclarationResolveTest : KotlinLightCodeInsightFix
|
|||||||
val declarationToResolve = lazyDeclarations.firstOrNull { it.name?.lowercase() == "resolveme" }
|
val declarationToResolve = lazyDeclarations.firstOrNull { it.name?.lowercase() == "resolveme" }
|
||||||
?: error("declaration with name `resolveMe` was not found")
|
?: error("declaration with name `resolveMe` was not found")
|
||||||
resolveWithClearCaches(ktFile) { firModuleResolveState ->
|
resolveWithClearCaches(ktFile) { firModuleResolveState ->
|
||||||
|
check(firModuleResolveState is FirModuleResolveStateImpl)
|
||||||
val rendered = declarationToResolve.withFirDeclaration(
|
val rendered = declarationToResolve.withFirDeclaration(
|
||||||
firModuleResolveState,
|
firModuleResolveState,
|
||||||
FirResolvePhase.BODY_RESOLVE
|
FirResolvePhase.BODY_RESOLVE
|
||||||
|
|||||||
+19
-35
@@ -7,12 +7,9 @@ package org.jetbrains.kotlin.idea.frontend.api.fir
|
|||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.symbolProvider
|
import org.jetbrains.kotlin.fir.resolve.symbolProvider
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
|
import org.jetbrains.kotlin.idea.fir.low.level.api.api.*
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.LowLevelFirApiFacadeForCompletion
|
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getFirFile
|
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.InvalidWayOfUsingAnalysisSession
|
import org.jetbrains.kotlin.idea.frontend.api.InvalidWayOfUsingAnalysisSession
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.components.KtVisibilityChecker
|
import org.jetbrains.kotlin.idea.frontend.api.components.KtVisibilityChecker
|
||||||
@@ -20,8 +17,6 @@ import org.jetbrains.kotlin.idea.frontend.api.components.KtSymbolDeclarationRend
|
|||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.components.*
|
import org.jetbrains.kotlin.idea.frontend.api.fir.components.*
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirOverrideInfoProvider
|
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirOverrideInfoProvider
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbolProvider
|
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbolProvider
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.EnclosingDeclarationContext
|
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.recordCompletionContext
|
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.threadLocal
|
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.threadLocal
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
|
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
@@ -33,9 +28,14 @@ private constructor(
|
|||||||
val firResolveState: FirModuleResolveState,
|
val firResolveState: FirModuleResolveState,
|
||||||
internal val firSymbolBuilder: KtSymbolByFirBuilder,
|
internal val firSymbolBuilder: KtSymbolByFirBuilder,
|
||||||
token: ValidityToken,
|
token: ValidityToken,
|
||||||
val context: KtFirAnalysisSessionContext,
|
private val mode: AnalysisSessionMode,
|
||||||
) : KtAnalysisSession(token) {
|
) : KtAnalysisSession(token) {
|
||||||
|
|
||||||
|
private enum class AnalysisSessionMode {
|
||||||
|
REGULAR,
|
||||||
|
DEPENDENT_COPY
|
||||||
|
}
|
||||||
|
|
||||||
override val smartCastProviderImpl = KtFirSmartcastProvider(this, token)
|
override val smartCastProviderImpl = KtFirSmartcastProvider(this, token)
|
||||||
|
|
||||||
override val expressionTypeProviderImpl = KtFirExpressionTypeProvider(this, token)
|
override val expressionTypeProviderImpl = KtFirExpressionTypeProvider(this, token)
|
||||||
@@ -73,19 +73,23 @@ private constructor(
|
|||||||
|
|
||||||
override val subtypingComponentImpl = KtFirSubtypingComponent(this, token)
|
override val subtypingComponentImpl = KtFirSubtypingComponent(this, token)
|
||||||
|
|
||||||
override fun createContextDependentCopy(originalKtFile: KtFile, fakeKtElement: KtElement): KtAnalysisSession {
|
override fun createContextDependentCopy(originalKtFile: KtFile, dependencyKtElement: KtElement): KtAnalysisSession {
|
||||||
check(context == KtFirAnalysisSessionContext.DefaultContext) {
|
check(mode == AnalysisSessionMode.REGULAR) {
|
||||||
"Cannot create context-dependent copy of KtAnalysis session from a context dependent one"
|
"Cannot create context-dependent copy of KtAnalysis session from a context dependent one"
|
||||||
}
|
}
|
||||||
val contextResolveState = LowLevelFirApiFacadeForCompletion.getResolveStateForCompletion(firResolveState)
|
|
||||||
val originalFirFile = originalKtFile.getFirFile(firResolveState)
|
val contextResolveState = LowLevelFirApiFacadeForDependentCopy.getResolveStateForDependedCopy(
|
||||||
val context = KtFirAnalysisSessionContext.FakeFileContext(originalKtFile, originalFirFile, fakeKtElement, contextResolveState)
|
originalState = firResolveState,
|
||||||
|
originalKtFile = originalKtFile,
|
||||||
|
dependencyKtElement = dependencyKtElement
|
||||||
|
)
|
||||||
|
|
||||||
return KtFirAnalysisSession(
|
return KtFirAnalysisSession(
|
||||||
project,
|
project,
|
||||||
contextResolveState,
|
contextResolveState,
|
||||||
firSymbolBuilder.createReadOnlyCopy(contextResolveState),
|
firSymbolBuilder.createReadOnlyCopy(contextResolveState),
|
||||||
token,
|
token,
|
||||||
context
|
AnalysisSessionMode.DEPENDENT_COPY
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,28 +114,8 @@ private constructor(
|
|||||||
firResolveState,
|
firResolveState,
|
||||||
firSymbolBuilder,
|
firSymbolBuilder,
|
||||||
token,
|
token,
|
||||||
KtFirAnalysisSessionContext.DefaultContext
|
AnalysisSessionMode.REGULAR
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal sealed class KtFirAnalysisSessionContext {
|
|
||||||
object DefaultContext : KtFirAnalysisSessionContext()
|
|
||||||
|
|
||||||
class FakeFileContext(
|
|
||||||
originalFile: KtFile,
|
|
||||||
firFile: FirFile,
|
|
||||||
fakeContextElement: KtElement,
|
|
||||||
fakeModuleResolveState: FirModuleResolveState
|
|
||||||
) : KtFirAnalysisSessionContext() {
|
|
||||||
init {
|
|
||||||
require(!fakeContextElement.isPhysical)
|
|
||||||
|
|
||||||
val enclosingContext = EnclosingDeclarationContext.detect(originalFile, fakeContextElement)
|
|
||||||
enclosingContext.recordCompletionContext(firFile, fakeModuleResolveState)
|
|
||||||
}
|
|
||||||
|
|
||||||
val fakeKtFile = fakeContextElement.containingKtFile
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-79
@@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2020 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.frontend.api.fir.utils
|
|
||||||
|
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
|
||||||
import com.intellij.psi.util.parentsOfType
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
|
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.LowLevelFirApiFacadeForCompletion
|
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.util.originalDeclaration
|
|
||||||
import org.jetbrains.kotlin.idea.util.getElementTextInContext
|
|
||||||
import org.jetbrains.kotlin.psi.*
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
|
||||||
import kotlin.reflect.KClass
|
|
||||||
|
|
||||||
internal sealed class EnclosingDeclarationContext {
|
|
||||||
abstract val fakeKtEnclosingDeclaration: KtDeclaration
|
|
||||||
abstract val originalKtEnclosingDeclaration: KtDeclaration
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private fun KtDeclaration.canBeEnclosingDeclaration(): Boolean = when (this) {
|
|
||||||
is KtNamedFunction -> isTopLevel || containingClassOrObject?.isLocal == false
|
|
||||||
is KtProperty -> isTopLevel || containingClassOrObject?.isLocal == false
|
|
||||||
is KtClassOrObject -> !isLocal
|
|
||||||
is KtTypeAlias -> isTopLevel() || containingClassOrObject?.isLocal == false
|
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun detect(originalFile: KtFile, positionInFakeFile: KtElement): EnclosingDeclarationContext {
|
|
||||||
val fakeKtDeclaration = positionInFakeFile.parentsOfType<KtNamedDeclaration>().firstOrNull { ktDeclaration ->
|
|
||||||
ktDeclaration.canBeEnclosingDeclaration()
|
|
||||||
}
|
|
||||||
if (fakeKtDeclaration != null) {
|
|
||||||
val originalDeclaration = findMatchingElementInCopy(fakeKtDeclaration, originalFile)
|
|
||||||
?: error("Cannot find original declaration matching to ${fakeKtDeclaration.getElementTextInContext()} in $originalFile")
|
|
||||||
recordOriginalDeclaration(originalDeclaration, fakeKtDeclaration)
|
|
||||||
return EnclosingDeclarationContextImpl(fakeKtDeclaration, originalDeclaration)
|
|
||||||
}
|
|
||||||
|
|
||||||
error("Cannot find enclosing declaration for ${positionInFakeFile.getElementTextInContext()}")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun recordOriginalDeclaration(originalDeclaration: KtNamedDeclaration, fakeDeclaration: KtNamedDeclaration) {
|
|
||||||
require(!fakeDeclaration.isPhysical)
|
|
||||||
require(originalDeclaration.containingKtFile !== fakeDeclaration.containingKtFile)
|
|
||||||
val originalDeclrationParents = originalDeclaration.parentsOfType<KtDeclaration>().toList()
|
|
||||||
val fakeDeclarationParents = fakeDeclaration.parentsOfType<KtDeclaration>().toList()
|
|
||||||
|
|
||||||
originalDeclrationParents.zip(fakeDeclarationParents) { original, fake ->
|
|
||||||
fake.originalDeclaration = original
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class EnclosingDeclarationContextImpl(
|
|
||||||
override val fakeKtEnclosingDeclaration: KtDeclaration,
|
|
||||||
override val originalKtEnclosingDeclaration: KtDeclaration
|
|
||||||
) : EnclosingDeclarationContext()
|
|
||||||
|
|
||||||
|
|
||||||
internal fun EnclosingDeclarationContext.recordCompletionContext(originalFirFile: FirFile, firResolveState: FirModuleResolveState) {
|
|
||||||
LowLevelFirApiFacadeForCompletion.recordCompletionContextForDeclaration(
|
|
||||||
originalFirFile,
|
|
||||||
fakeKtEnclosingDeclaration,
|
|
||||||
originalKtEnclosingDeclaration,
|
|
||||||
state = firResolveState,
|
|
||||||
fakeContainingFile = fakeKtEnclosingDeclaration.containingKtFile
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T : KtElement> findMatchingElementInCopy(element: T, copy: KtFile): T? {
|
|
||||||
val elementOffset = element.textOffset
|
|
||||||
val elementAtOffset = copy.findElementAt(elementOffset) ?: return null
|
|
||||||
return PsiTreeUtil.getParentOfType(elementAtOffset, element::class.java, false)?.takeIf { it.textOffset == elementOffset }
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user