FIR IDE: simplify completion context retrieving
This commit is contained in:
committed by
TeamCityServer
parent
f8efe3b5df
commit
a5c33c8d42
+2
-4
@@ -70,12 +70,10 @@ internal class FirModuleResolveStateForCompletion(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun lazyResolveDeclarationForCompletion(
|
override fun lazyResolveDeclarationForCompletion(
|
||||||
firFunction: FirDeclaration,
|
firDeclaration: FirDeclaration,
|
||||||
containerFirFile: FirFile,
|
containerFirFile: FirFile,
|
||||||
firIdeProvider: FirProvider,
|
|
||||||
toPhase: FirResolvePhase,
|
|
||||||
) {
|
) {
|
||||||
originalState.lazyResolveDeclarationForCompletion(firFunction, containerFirFile, firIdeProvider, toPhase)
|
originalState.lazyResolveDeclarationForCompletion(firDeclaration, containerFirFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getFirFile(declaration: FirDeclaration, cache: ModuleFileCache): FirFile? {
|
override fun getFirFile(declaration: FirDeclaration, cache: ModuleFileCache): FirFile? {
|
||||||
|
|||||||
+5
-7
@@ -157,19 +157,17 @@ internal class FirModuleResolveStateImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun lazyResolveDeclarationForCompletion(
|
override fun lazyResolveDeclarationForCompletion(
|
||||||
firFunction: FirDeclaration,
|
firDeclaration: FirDeclaration,
|
||||||
containerFirFile: FirFile,
|
containerFirFile: FirFile,
|
||||||
firIdeProvider: FirProvider,
|
|
||||||
toPhase: FirResolvePhase,
|
|
||||||
) {
|
) {
|
||||||
firFileBuilder.runCustomResolveWithPCECheck(containerFirFile, rootModuleSession.cache) {
|
firFileBuilder.runCustomResolveWithPCECheck(containerFirFile, rootModuleSession.cache) {
|
||||||
firLazyDeclarationResolver.runLazyResolveWithoutLock(
|
firLazyDeclarationResolver.runLazyResolveWithoutLock(
|
||||||
firFunction,
|
firDeclaration,
|
||||||
rootModuleSession.cache,
|
rootModuleSession.cache,
|
||||||
containerFirFile,
|
containerFirFile,
|
||||||
firIdeProvider,
|
containerFirFile.session.firIdeProvider,
|
||||||
fromPhase = firFunction.resolvePhase,
|
fromPhase = firDeclaration.resolvePhase,
|
||||||
toPhase,
|
toPhase = FirResolvePhase.BODY_RESOLVE,
|
||||||
towerDataContextCollector = collector,
|
towerDataContextCollector = collector,
|
||||||
checkPCE = true
|
checkPCE = true
|
||||||
)
|
)
|
||||||
|
|||||||
+118
@@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* 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.FirElement
|
||||||
|
import org.jetbrains.kotlin.fir.builder.RawFirFragmentForLazyBodiesBuilder
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.builder.buildPropertyAccessorCopy
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunctionCopy
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
|
||||||
|
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||||
|
import org.jetbrains.kotlin.idea.fir.low.level.api.providers.firIdeProvider
|
||||||
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
|
import org.jetbrains.kotlin.psi.KtProperty
|
||||||
|
|
||||||
|
object DeclarationCopyBuilder {
|
||||||
|
fun createDeclarationCopy(
|
||||||
|
originalFirDeclaration: FirDeclaration,
|
||||||
|
fakeKtDeclaration: KtDeclaration,
|
||||||
|
state: FirModuleResolveState,
|
||||||
|
): FirDeclaration {
|
||||||
|
return when (fakeKtDeclaration) {
|
||||||
|
is KtNamedFunction -> buildFunctionCopy(
|
||||||
|
fakeKtDeclaration,
|
||||||
|
originalFirDeclaration as FirSimpleFunction,
|
||||||
|
state
|
||||||
|
)
|
||||||
|
is KtProperty -> buildPropertyCopy(
|
||||||
|
fakeKtDeclaration,
|
||||||
|
originalFirDeclaration as FirProperty,
|
||||||
|
state
|
||||||
|
)
|
||||||
|
else -> error("Unsupported declaration ${fakeKtDeclaration::class.simpleName}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildFunctionCopy(
|
||||||
|
element: KtNamedFunction,
|
||||||
|
originalFunction: FirSimpleFunction,
|
||||||
|
state: FirModuleResolveState,
|
||||||
|
): FirSimpleFunction {
|
||||||
|
val builtFunction = createCopy(element, originalFunction) as FirSimpleFunction
|
||||||
|
|
||||||
|
// right now we can't resolve builtFunction header properly, as it built right in air,
|
||||||
|
// without file, which is now required for running stages other then body resolve, so we
|
||||||
|
// take original function header (which is resolved) and copy replacing body with body from builtFunction
|
||||||
|
return buildSimpleFunctionCopy(originalFunction) {
|
||||||
|
body = builtFunction.body
|
||||||
|
symbol = builtFunction.symbol
|
||||||
|
resolvePhase = minOf(originalFunction.resolvePhase, FirResolvePhase.DECLARATIONS)
|
||||||
|
source = builtFunction.source
|
||||||
|
session = state.rootModuleSession
|
||||||
|
}.apply { reassignAllReturnTargets(builtFunction) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildPropertyCopy(
|
||||||
|
element: KtProperty,
|
||||||
|
originalProperty: FirProperty,
|
||||||
|
state: FirModuleResolveState
|
||||||
|
): FirProperty {
|
||||||
|
val builtProperty = createCopy(element, originalProperty) as FirProperty
|
||||||
|
|
||||||
|
val originalSetter = originalProperty.setter
|
||||||
|
val builtSetter = builtProperty.setter
|
||||||
|
|
||||||
|
// setter has a header with `value` parameter, and we want it type to be resolved
|
||||||
|
val copySetter = if (originalSetter != null && builtSetter != null) {
|
||||||
|
buildPropertyAccessorCopy(originalSetter) {
|
||||||
|
body = builtSetter.body
|
||||||
|
symbol = builtSetter.symbol
|
||||||
|
resolvePhase = minOf(builtSetter.resolvePhase, FirResolvePhase.DECLARATIONS)
|
||||||
|
source = builtSetter.source
|
||||||
|
session = state.rootModuleSession
|
||||||
|
}.apply { reassignAllReturnTargets(builtSetter) }
|
||||||
|
} else {
|
||||||
|
builtSetter
|
||||||
|
}
|
||||||
|
|
||||||
|
return org.jetbrains.kotlin.fir.declarations.builder.buildPropertyCopy(originalProperty) {
|
||||||
|
symbol = builtProperty.symbol
|
||||||
|
initializer = builtProperty.initializer
|
||||||
|
|
||||||
|
getter = builtProperty.getter
|
||||||
|
setter = copySetter
|
||||||
|
|
||||||
|
resolvePhase = minOf(originalProperty.resolvePhase, FirResolvePhase.DECLARATIONS)
|
||||||
|
source = builtProperty.source
|
||||||
|
session = state.rootModuleSession
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createCopy(
|
||||||
|
fakeKtDeclaration: KtDeclaration,
|
||||||
|
originalFirDeclaration: FirDeclaration,
|
||||||
|
): FirDeclaration {
|
||||||
|
return RawFirFragmentForLazyBodiesBuilder.build(
|
||||||
|
session = originalFirDeclaration.session,
|
||||||
|
baseScopeProvider = originalFirDeclaration.session.firIdeProvider.kotlinScopeProvider,
|
||||||
|
designation = originalFirDeclaration.collectDesignation().fullDesignation,
|
||||||
|
declaration = fakeKtDeclaration
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirFunction<*>.reassignAllReturnTargets(from: FirFunction<*>) {
|
||||||
|
this.accept(object : FirVisitorVoid() {
|
||||||
|
override fun visitElement(element: FirElement) {
|
||||||
|
if (element is FirReturnExpression && element.target.labeledElement == from) {
|
||||||
|
element.target.bind(this@reassignAllReturnTargets)
|
||||||
|
}
|
||||||
|
element.acceptChildren(this)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-3
@@ -83,10 +83,8 @@ abstract class FirModuleResolveState {
|
|||||||
|
|
||||||
// todo temporary, used only in completion
|
// todo temporary, used only in completion
|
||||||
internal abstract fun lazyResolveDeclarationForCompletion(
|
internal abstract fun lazyResolveDeclarationForCompletion(
|
||||||
firFunction: FirDeclaration,
|
firDeclaration: FirDeclaration,
|
||||||
containerFirFile: FirFile,
|
containerFirFile: FirFile,
|
||||||
firIdeProvider: FirProvider,
|
|
||||||
toPhase: FirResolvePhase,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
internal abstract fun getFirFile(declaration: FirDeclaration, cache: ModuleFileCache): FirFile?
|
internal abstract fun getFirFile(declaration: FirDeclaration, cache: ModuleFileCache): FirFile?
|
||||||
|
|||||||
+10
-104
@@ -5,20 +5,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.fir.low.level.api.api
|
package org.jetbrains.kotlin.idea.fir.low.level.api.api
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.builder.buildPropertyAccessorCopy
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.builder.buildPropertyCopy
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunctionCopy
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveStateForCompletion
|
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveStateForCompletion
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveStateImpl
|
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveStateImpl
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirIdeProvider
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.providers.firIdeProvider
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
|
||||||
import org.jetbrains.kotlin.psi.KtProperty
|
|
||||||
|
|
||||||
object LowLevelFirApiFacadeForCompletion {
|
object LowLevelFirApiFacadeForCompletion {
|
||||||
fun getResolveStateForCompletion(originalState: FirModuleResolveState): FirModuleResolveState {
|
fun getResolveStateForCompletion(originalState: FirModuleResolveState): FirModuleResolveState {
|
||||||
@@ -26,102 +17,17 @@ object LowLevelFirApiFacadeForCompletion {
|
|||||||
return FirModuleResolveStateForCompletion(originalState.project, originalState)
|
return FirModuleResolveStateForCompletion(originalState.project, originalState)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun recordCompletionContextForFunction(
|
fun recordCompletionContextForDeclaration(
|
||||||
firFile: FirFile,
|
firFile: FirFile,
|
||||||
fakeElement: KtNamedFunction,
|
fakeKtDeclaration: KtDeclaration,
|
||||||
originalElement: KtNamedFunction,
|
originalKtDeclaration: KtDeclaration,
|
||||||
|
fakeContainingFile: KtFile,
|
||||||
state: FirModuleResolveState,
|
state: FirModuleResolveState,
|
||||||
) {
|
) {
|
||||||
val firIdeProvider = firFile.session.firIdeProvider
|
val originalFirDeclaration = originalKtDeclaration.getOrBuildFirOfType<FirDeclaration>(state)
|
||||||
|
val fakeFirDeclaration = DeclarationCopyBuilder.createDeclarationCopy(originalFirDeclaration, fakeKtDeclaration, state)
|
||||||
|
|
||||||
val originalFunction = state.getOrBuildFirFor(originalElement) as FirSimpleFunction
|
state.lazyResolveDeclarationForCompletion(fakeFirDeclaration, firFile)
|
||||||
val copyFunction = buildFunctionCopyForCompletion(firIdeProvider, fakeElement, originalFunction, state)
|
state.recordPsiToFirMappingsForCompletionFrom(fakeFirDeclaration, firFile, fakeContainingFile)
|
||||||
|
|
||||||
state.lazyResolveDeclarationForCompletion(copyFunction, firFile, firIdeProvider, FirResolvePhase.BODY_RESOLVE)
|
|
||||||
state.recordPsiToFirMappingsForCompletionFrom(copyFunction, firFile, fakeElement.containingKtFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun recordCompletionContextForProperty(
|
|
||||||
firFile: FirFile,
|
|
||||||
fakeElement: KtProperty,
|
|
||||||
originalElement: KtProperty,
|
|
||||||
state: FirModuleResolveState,
|
|
||||||
) {
|
|
||||||
val firIdeProvider = firFile.session.firIdeProvider
|
|
||||||
|
|
||||||
val originalProperty = state.getOrBuildFirFor(originalElement) as FirProperty
|
|
||||||
val copyProperty = buildPropertyCopyForCompletion(firIdeProvider, fakeElement, originalProperty, state)
|
|
||||||
|
|
||||||
state.lazyResolveDeclarationForCompletion(copyProperty, firFile, firIdeProvider, FirResolvePhase.BODY_RESOLVE)
|
|
||||||
state.recordPsiToFirMappingsForCompletionFrom(copyProperty, firFile, fakeElement.containingKtFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildFunctionCopyForCompletion(
|
|
||||||
firIdeProvider: FirIdeProvider,
|
|
||||||
element: KtNamedFunction,
|
|
||||||
originalFunction: FirSimpleFunction,
|
|
||||||
state: FirModuleResolveState,
|
|
||||||
): FirSimpleFunction {
|
|
||||||
val builtFunction = firIdeProvider.buildFunctionWithBody(element, originalFunction)
|
|
||||||
|
|
||||||
// right now we can't resolve builtFunction header properly, as it built right in air,
|
|
||||||
// without file, which is now required for running stages other then body resolve, so we
|
|
||||||
// take original function header (which is resolved) and copy replacing body with body from builtFunction
|
|
||||||
return buildSimpleFunctionCopy(originalFunction) {
|
|
||||||
body = builtFunction.body
|
|
||||||
symbol = builtFunction.symbol as FirNamedFunctionSymbol
|
|
||||||
resolvePhase = minOf(originalFunction.resolvePhase, FirResolvePhase.DECLARATIONS)
|
|
||||||
source = builtFunction.source
|
|
||||||
session = state.rootModuleSession
|
|
||||||
}.apply { reassignAllReturnTargets(builtFunction) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildPropertyCopyForCompletion(
|
|
||||||
firIdeProvider: FirIdeProvider,
|
|
||||||
element: KtProperty,
|
|
||||||
originalProperty: FirProperty,
|
|
||||||
state: FirModuleResolveState
|
|
||||||
): FirProperty {
|
|
||||||
val builtProperty = firIdeProvider.buildPropertyWithBody(element, originalProperty)
|
|
||||||
|
|
||||||
val originalSetter = originalProperty.setter
|
|
||||||
val builtSetter = builtProperty.setter
|
|
||||||
|
|
||||||
// setter has a header with `value` parameter, and we want it type to be resolved
|
|
||||||
val copySetter = if (originalSetter != null && builtSetter != null) {
|
|
||||||
buildPropertyAccessorCopy(originalSetter) {
|
|
||||||
body = builtSetter.body
|
|
||||||
symbol = builtSetter.symbol
|
|
||||||
resolvePhase = minOf(builtSetter.resolvePhase, FirResolvePhase.DECLARATIONS)
|
|
||||||
source = builtSetter.source
|
|
||||||
session = state.rootModuleSession
|
|
||||||
}.apply { reassignAllReturnTargets(builtSetter) }
|
|
||||||
} else {
|
|
||||||
builtSetter
|
|
||||||
}
|
|
||||||
|
|
||||||
return buildPropertyCopy(originalProperty) {
|
|
||||||
symbol = builtProperty.symbol
|
|
||||||
initializer = builtProperty.initializer
|
|
||||||
|
|
||||||
getter = builtProperty.getter
|
|
||||||
setter = copySetter
|
|
||||||
|
|
||||||
resolvePhase = minOf(originalProperty.resolvePhase, FirResolvePhase.DECLARATIONS)
|
|
||||||
source = builtProperty.source
|
|
||||||
session = state.rootModuleSession
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun FirFunction<*>.reassignAllReturnTargets(from: FirFunction<*>) {
|
|
||||||
this.accept(object : FirVisitorVoid() {
|
|
||||||
override fun visitElement(element: FirElement) {
|
|
||||||
if (element is FirReturnExpression && element.target.labeledElement == from) {
|
|
||||||
element.target.bind(this@reassignAllReturnTargets)
|
|
||||||
}
|
|
||||||
element.acceptChildren(this)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.psi
|
|||||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||||
|
import org.jetbrains.kotlin.idea.fir.low.level.api.api.DeclarationCopyBuilder
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics.FileDiagnosticRetriever
|
import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics.FileDiagnosticRetriever
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics.FileStructureElementDiagnostics
|
import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics.FileStructureElementDiagnostics
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics.SingleNonLocalDeclarationDiagnosticRetriever
|
import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics.SingleNonLocalDeclarationDiagnosticRetriever
|
||||||
@@ -79,7 +80,7 @@ internal class ReanalyzableFunctionStructureElement(
|
|||||||
towerDataContextCollector: FirTowerDataContextCollector,
|
towerDataContextCollector: FirTowerDataContextCollector,
|
||||||
): ReanalyzableFunctionStructureElement {
|
): ReanalyzableFunctionStructureElement {
|
||||||
val originalFunction = firSymbol.fir as FirSimpleFunction
|
val originalFunction = firSymbol.fir as FirSimpleFunction
|
||||||
val newFunction = firIdeProvider.buildFunctionWithBody(newKtDeclaration, originalFunction) as FirSimpleFunction
|
val newFunction = DeclarationCopyBuilder.createCopy(newKtDeclaration, originalFunction) as FirSimpleFunction
|
||||||
|
|
||||||
return FileStructureUtil.withDeclarationReplaced(firFile, cache, originalFunction, newFunction) {
|
return FileStructureUtil.withDeclarationReplaced(firFile, cache, originalFunction, newFunction) {
|
||||||
firLazyDeclarationResolver.lazyResolveDeclaration(
|
firLazyDeclarationResolver.lazyResolveDeclaration(
|
||||||
@@ -121,7 +122,7 @@ internal class ReanalyzablePropertyStructureElement(
|
|||||||
towerDataContextCollector: FirTowerDataContextCollector,
|
towerDataContextCollector: FirTowerDataContextCollector,
|
||||||
): ReanalyzablePropertyStructureElement {
|
): ReanalyzablePropertyStructureElement {
|
||||||
val originalProperty = firSymbol.fir
|
val originalProperty = firSymbol.fir
|
||||||
val newProperty = firIdeProvider.buildPropertyWithBody(newKtDeclaration, originalProperty)
|
val newProperty = DeclarationCopyBuilder.createCopy(newKtDeclaration, originalProperty) as FirProperty
|
||||||
|
|
||||||
return FileStructureUtil.withDeclarationReplaced(firFile, cache, originalProperty, newProperty) {
|
return FileStructureUtil.withDeclarationReplaced(firFile, cache, originalProperty, newProperty) {
|
||||||
firLazyDeclarationResolver.lazyResolveDeclaration(
|
firLazyDeclarationResolver.lazyResolveDeclaration(
|
||||||
|
|||||||
-26
@@ -91,32 +91,6 @@ internal class FirIdeProvider(
|
|||||||
override fun getFirFilesByPackage(fqName: FqName): List<FirFile> = error("Should not be called in FIR IDE")
|
override fun getFirFilesByPackage(fqName: FqName): List<FirFile> = error("Should not be called in FIR IDE")
|
||||||
|
|
||||||
|
|
||||||
// TODO move out of here
|
|
||||||
// used only for completion
|
|
||||||
fun buildFunctionWithBody(
|
|
||||||
ktNamedFunction: KtNamedFunction,
|
|
||||||
original: FirFunction<*>,
|
|
||||||
): FirFunction<*> {
|
|
||||||
return RawFirFragmentForLazyBodiesBuilder.build(
|
|
||||||
session = original.session,
|
|
||||||
baseScopeProvider = original.session.firIdeProvider.kotlinScopeProvider,
|
|
||||||
designation = original.collectDesignation().fullDesignation,
|
|
||||||
declaration = ktNamedFunction
|
|
||||||
) as FirFunction<*>
|
|
||||||
}
|
|
||||||
|
|
||||||
fun buildPropertyWithBody(
|
|
||||||
ktNamedFunction: KtProperty,
|
|
||||||
original: FirProperty,
|
|
||||||
): FirProperty {
|
|
||||||
return RawFirFragmentForLazyBodiesBuilder.build(
|
|
||||||
session = original.session,
|
|
||||||
baseScopeProvider = original.session.firIdeProvider.kotlinScopeProvider,
|
|
||||||
designation = original.collectDesignation().fullDesignation,
|
|
||||||
declaration = ktNamedFunction
|
|
||||||
) as FirProperty
|
|
||||||
}
|
|
||||||
|
|
||||||
@FirProviderInternals
|
@FirProviderInternals
|
||||||
override fun recordGeneratedClass(owner: FirAnnotatedDeclaration, klass: FirRegularClass) {
|
override fun recordGeneratedClass(owner: FirAnnotatedDeclaration, klass: FirRegularClass) {
|
||||||
TODO()
|
TODO()
|
||||||
|
|||||||
+34
-50
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.frontend.api.fir.utils
|
package org.jetbrains.kotlin.idea.frontend.api.fir.utils
|
||||||
|
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import com.intellij.psi.util.parentsOfType
|
import com.intellij.psi.util.parentsOfType
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
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.FirModuleResolveState
|
||||||
@@ -13,30 +14,30 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.util.originalDeclaration
|
|||||||
import org.jetbrains.kotlin.idea.util.getElementTextInContext
|
import org.jetbrains.kotlin.idea.util.getElementTextInContext
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
internal sealed class EnclosingDeclarationContext {
|
internal sealed class EnclosingDeclarationContext {
|
||||||
|
abstract val fakeKtEnclosingDeclaration: KtDeclaration
|
||||||
|
abstract val originalKtEnclosingDeclaration: KtDeclaration
|
||||||
|
|
||||||
companion object {
|
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 {
|
fun detect(originalFile: KtFile, positionInFakeFile: KtElement): EnclosingDeclarationContext {
|
||||||
val fakeFunction = positionInFakeFile.parentsOfType<KtNamedFunction>().firstOrNull {
|
val fakeKtDeclaration = positionInFakeFile.parentsOfType<KtNamedDeclaration>().firstOrNull { ktDeclaration ->
|
||||||
it.isTopLevel || it.containingClassOrObject?.isLocal == false
|
ktDeclaration.canBeEnclosingDeclaration()
|
||||||
}
|
}
|
||||||
if (fakeFunction != null) {
|
if (fakeKtDeclaration != null) {
|
||||||
val originalFunction = originalFile.findDeclarationOfTypeAt<KtNamedFunction>(fakeFunction.textOffset)
|
val originalDeclaration = originalFile.findDeclarationOfTypeAt(fakeKtDeclaration.textOffset, fakeKtDeclaration::class)
|
||||||
?: error("Cannot find original function matching to ${fakeFunction.getElementTextInContext()} in $originalFile")
|
?: error("Cannot find original function matching to ${fakeKtDeclaration.getElementTextInContext()} in $originalFile")
|
||||||
recordOriginalDeclaration(originalFunction, fakeFunction)
|
recordOriginalDeclaration(originalDeclaration, fakeKtDeclaration)
|
||||||
return FunctionContext(fakeFunction, originalFunction)
|
return EnclosingDeclarationContextImpl(fakeKtDeclaration, originalDeclaration)
|
||||||
}
|
|
||||||
|
|
||||||
val fakeProperty = positionInFakeFile.parentsOfType<KtProperty>().firstOrNull {
|
|
||||||
it.isTopLevel || it.containingClassOrObject?.isLocal == false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fakeProperty != null) {
|
|
||||||
val originalProperty = originalFile.findDeclarationOfTypeAt<KtProperty>(fakeProperty.textOffset)
|
|
||||||
?: error("Cannot find original property matching to ${fakeProperty.getElementTextInContext()} in $originalFile")
|
|
||||||
recordOriginalDeclaration(originalProperty, fakeProperty)
|
|
||||||
return PropertyContext(fakeProperty, originalProperty)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error("Cannot find enclosing declaration for ${positionInFakeFile.getElementTextInContext()}")
|
error("Cannot find enclosing declaration for ${positionInFakeFile.getElementTextInContext()}")
|
||||||
@@ -55,41 +56,24 @@ internal sealed class EnclosingDeclarationContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class FunctionContext(
|
internal class EnclosingDeclarationContextImpl(
|
||||||
val fakeEnclosingFunction: KtNamedFunction,
|
override val fakeKtEnclosingDeclaration: KtDeclaration,
|
||||||
val originalEnclosingFunction: KtNamedFunction
|
override val originalKtEnclosingDeclaration: KtDeclaration
|
||||||
) : EnclosingDeclarationContext()
|
) : EnclosingDeclarationContext()
|
||||||
|
|
||||||
internal class PropertyContext(
|
|
||||||
val fakeEnclosingProperty: KtProperty,
|
|
||||||
val originalEnclosingProperty: KtProperty
|
|
||||||
) : EnclosingDeclarationContext()
|
|
||||||
|
|
||||||
internal val EnclosingDeclarationContext.fakeEnclosingDeclaration: KtCallableDeclaration
|
|
||||||
get() = when (this) {
|
|
||||||
is FunctionContext -> fakeEnclosingFunction
|
|
||||||
is PropertyContext -> fakeEnclosingProperty
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun EnclosingDeclarationContext.recordCompletionContext(originalFirFile: FirFile, firResolveState: FirModuleResolveState) {
|
internal fun EnclosingDeclarationContext.recordCompletionContext(originalFirFile: FirFile, firResolveState: FirModuleResolveState) {
|
||||||
when (this) {
|
LowLevelFirApiFacadeForCompletion.recordCompletionContextForDeclaration(
|
||||||
is FunctionContext -> LowLevelFirApiFacadeForCompletion.recordCompletionContextForFunction(
|
originalFirFile,
|
||||||
originalFirFile,
|
fakeKtEnclosingDeclaration,
|
||||||
fakeEnclosingFunction,
|
originalKtEnclosingDeclaration,
|
||||||
originalEnclosingFunction,
|
state = firResolveState,
|
||||||
state = firResolveState
|
fakeContainingFile = fakeKtEnclosingDeclaration.containingKtFile
|
||||||
)
|
)
|
||||||
|
|
||||||
is PropertyContext -> LowLevelFirApiFacadeForCompletion.recordCompletionContextForProperty(
|
|
||||||
originalFirFile,
|
|
||||||
fakeEnclosingProperty,
|
|
||||||
originalEnclosingProperty,
|
|
||||||
state = firResolveState
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <reified T : KtElement> KtFile.findDeclarationOfTypeAt(offset: Int): T? =
|
private fun <T : KtElement> KtFile.findDeclarationOfTypeAt(offset: Int, declarationType: KClass<T>): T? {
|
||||||
findElementAt(offset)
|
val elementAtOffset = findElementAt(offset) ?: return null
|
||||||
?.getNonStrictParentOfType<T>()
|
return PsiTreeUtil.getParentOfType(elementAtOffset, declarationType.java, false)?.takeIf { it.textOffset == offset }
|
||||||
?.takeIf { it.textOffset == offset }
|
}
|
||||||
Reference in New Issue
Block a user