Skip to content

Commit

Permalink
FIR IDE: fix reference resolving of qualified expression with nested …
Browse files Browse the repository at this point in the history
…classes
  • Loading branch information
darthorimar committed Nov 23, 2020
1 parent 164f4d1 commit e4d2e38
Showing 1 changed file with 34 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -139,42 +139,44 @@ internal object FirReferenceResolveHelper {
val fir = expression.getOrBuildFir(analysisSession.firResolveState)
val session = analysisSession.firResolveState.rootModuleSession
when (fir) {
is FirResolvable -> {
val calleeReference =
if (fir is FirFunctionCall
&& fir.isImplicitFunctionCall()
&& expression is KtNameReferenceExpression
) {
// we are resolving implicit invoke call, like
// fun foo(a: () -> Unit) {
// <expression>a</expression>()
// }
(fir.dispatchReceiver as FirQualifiedAccessExpression).calleeReference
} else fir.calleeReference
return listOfNotNull(calleeReference.toTargetSymbol(session, symbolBuilder))
}
is FirResolvedTypeRef -> {
if (expression.isPartOfUserTypeRefQualifier()) {
return listOfNotNull(getPackageSymbolFor(expression, symbolBuilder, forQualifiedType = true))
}
return listOfNotNull(fir.toTargetSymbol(session, symbolBuilder))
}
is FirResolvedQualifier -> {
// TODO refactor that block
val classId = fir.classId ?: return emptyList()

var parent = expression.parent as? KtDotQualifiedExpression
// Distinguish A.foo() from A(.Companion).foo()
// Make expression.parent as? KtDotQualifiedExpression local function
var parent = expression.parent as? KtDotQualifiedExpression
while (parent != null) {
val selectorExpression = parent.selectorExpression ?: break
if (selectorExpression === expression) {
parent = parent.parent as? KtDotQualifiedExpression
continue
}
val receiverClassId = if (parent.receiverExpression == expression) {
/*
* <caret>A.Named.i -> class A
*/
val name = fir.relativeClassFqName?.pathSegments()?.firstOrNull()
name?.let { ClassId(fir.packageFqName, it) }
} else null
val parentFir = selectorExpression.getOrBuildFir(analysisSession.firResolveState)
if (parentFir is FirQualifiedAccess) {
return listOfNotNull(classId.toTargetPsi(session, symbolBuilder, parentFir.calleeReference))
when {
parentFir is FirQualifiedAccess -> {
return listOfNotNull(
(receiverClassId ?: classId).toTargetPsi(session, symbolBuilder, parentFir.calleeReference)
)
}
receiverClassId != null -> {
return listOfNotNull(receiverClassId.toTargetPsi(session, symbolBuilder))
}
else -> parent = parent.parent as? KtDotQualifiedExpression
}
parent = parent.parent as? KtDotQualifiedExpression
}
return listOfNotNull(classId.toTargetPsi(session, symbolBuilder))
}
Expand Down Expand Up @@ -230,6 +232,20 @@ internal object FirReferenceResolveHelper {
}
return candidates.mapNotNull { it.fir.buildSymbol(symbolBuilder) }
}
is FirResolvable -> {
val calleeReference =
if (fir is FirFunctionCall
&& fir.isImplicitFunctionCall()
&& expression is KtNameReferenceExpression
) {
// we are resolving implicit invoke call, like
// fun foo(a: () -> Unit) {
// <expression>a</expression>()
// }
(fir.dispatchReceiver as FirQualifiedAccessExpression).calleeReference
} else fir.calleeReference
return listOfNotNull(calleeReference.toTargetSymbol(session, symbolBuilder))
}
else -> {
// Handle situation when we're in the middle/beginning of qualifier
// <caret>A.B.C.foo() or A.<caret>B.C.foo()
Expand Down

0 comments on commit e4d2e38

Please sign in to comment.