FIR IDE: fix completion on parenthesized expression

This commit is contained in:
Ilya Kirillov
2020-09-16 13:06:18 +03:00
parent 879cf3b049
commit 04fca93b1e
2 changed files with 19 additions and 12 deletions
@@ -32,7 +32,7 @@ internal class FirModuleResolveStateForCompletion(
originalState.getSessionFor(moduleInfo) originalState.getSessionFor(moduleInfo)
override fun getOrBuildFirFor(element: KtElement, toPhase: FirResolvePhase): FirElement { override fun getOrBuildFirFor(element: KtElement, toPhase: FirResolvePhase): FirElement {
completionMapping[element]?.let { return it } completionMapping[originalState.elementBuilder.getPsiAsFirElementSource(element)]?.let { return it }
return originalState.elementBuilder.getOrBuildFirFor( return originalState.elementBuilder.getOrBuildFirFor(
element, element,
originalState.rootModuleSession.cache, originalState.rootModuleSession.cache,
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.file.structure.FileStructureC
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.psi2ir.deparenthesize
/** /**
* Maps [KtElement] to [FirElement] * Maps [KtElement] to [FirElement]
@@ -23,6 +24,22 @@ import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
*/ */
@ThreadSafe @ThreadSafe
internal class FirElementBuilder { internal class FirElementBuilder {
fun getPsiAsFirElementSource(element: KtElement): KtElement {
val deparenthesized = if (element is KtPropertyDelegate) element.deparenthesize() else element
return when {
deparenthesized is KtParenthesizedExpression -> deparenthesized.deparenthesize()
deparenthesized is KtPropertyDelegate -> deparenthesized.expression ?: element
deparenthesized is KtQualifiedExpression && deparenthesized.selectorExpression is KtCallExpression -> {
/*
KtQualifiedExpression with KtCallExpression in selector transformed in FIR to FirFunctionCall expression
Which will have a receiver as qualifier
*/
deparenthesized.selectorExpression ?: error("Incomplete code:\n${element.getElementTextInContext()}")
}
else -> deparenthesized
}
}
fun getOrBuildFirFor( fun getOrBuildFirFor(
element: KtElement, element: KtElement,
moduleFileCache: ModuleFileCache, moduleFileCache: ModuleFileCache,
@@ -31,17 +48,7 @@ internal class FirElementBuilder {
val fileStructure = fileStructureCache.getFileStructure(element.containingKtFile, moduleFileCache) val fileStructure = fileStructureCache.getFileStructure(element.containingKtFile, moduleFileCache)
val mappings = fileStructure.getStructureElementFor(element).mappings val mappings = fileStructure.getStructureElementFor(element).mappings
val psi = when { val psi = getPsiAsFirElementSource(element)
element is KtPropertyDelegate -> element.expression ?: element
element is KtQualifiedExpression && element.selectorExpression is KtCallExpression -> {
/*
KtQualifiedExpression with KtCallExpression in selector transformed in FIR to FirFunctionCall expression
Which will have a receiver as qualifier
*/
element.selectorExpression ?: error("Incomplete code:\n${element.getElementTextInContext()}")
}
else -> element
}
mappings[psi]?.let { return it } mappings[psi]?.let { return it }
return psi.getFirOfClosestParent(mappings)?.second return psi.getFirOfClosestParent(mappings)?.second
?: error("FirElement is not found for:\n${element.getElementTextInContext()}") ?: error("FirElement is not found for:\n${element.getElementTextInContext()}")