KT-60957 [Analysis API] Visit FirPropertyAccessExpressions instead of FirResolvedNamedReferences

It's much easier to analyze complex cases like invoke operator calls
using dedicated `FirPropertyAccessExpression`
This commit is contained in:
Roman Golyshev
2023-08-07 23:14:11 +02:00
committed by teamcity
parent b0b2e76e13
commit 7633e6e6f1
@@ -404,18 +404,18 @@ private class ElementsToShortenCollector(
processTypeQualifier(errorResolvedQualifier)
}
override fun visitResolvedNamedReference(resolvedNamedReference: FirResolvedNamedReference) {
super.visitResolvedNamedReference(resolvedNamedReference)
processPropertyReference(resolvedNamedReference)
}
override fun visitFunctionCall(functionCall: FirFunctionCall) {
super.visitFunctionCall(functionCall)
processFunctionCall(functionCall)
}
override fun visitPropertyAccessExpression(propertyAccessExpression: FirPropertyAccessExpression) {
super.visitPropertyAccessExpression(propertyAccessExpression)
processPropertyAccess(propertyAccessExpression)
}
private fun processTypeRef(resolvedTypeRef: FirResolvedTypeRef) {
val typeElement = resolvedTypeRef.correspondingTypePsi ?: return
if (typeElement.referenceExpression?.textRange?.intersects(selection) != true) return
@@ -984,46 +984,38 @@ private class ElementsToShortenCollector(
return false
}
private fun processPropertyReference(resolvedNamedReference: FirResolvedNamedReference) {
val referenceExpression = resolvedNamedReference.psi as? KtNameReferenceExpression ?: return
if (!referenceExpression.textRange.intersects(selection)) return
val qualifiedProperty = referenceExpression.getDotQualifiedExpressionForSelector() ?: return
private fun processPropertyAccess(firPropertyAccess: FirPropertyAccessExpression) {
val propertyReferenceExpression = (firPropertyAccess.psi as? KtDotQualifiedExpression)?.selectorExpression as? KtNameReferenceExpression ?: return
if (!propertyReferenceExpression.textRange.intersects(selection)) return
val callableSymbol = resolvedNamedReference.resolvedSymbol as? FirCallableSymbol<*> ?: return
val qualifiedProperty = propertyReferenceExpression.getQualifiedElement() as? KtDotQualifiedExpression ?: return
val propertySymbol = firPropertyAccess.referencedSymbol ?: return
val option = callableShortenOption(callableSymbol)
val option = callableShortenOption(propertySymbol)
if (option == ShortenOption.DO_NOT_SHORTEN) return
val scopes = shorteningContext.findScopesAtPosition(qualifiedProperty, getNamesToImport(), towerContextProvider) ?: return
val availableCallables = shorteningContext.findPropertiesInScopes(scopes, callableSymbol.name)
val firPropertyAccess = qualifiedProperty.getCorrespondingPropertyAccessExpression() ?: return
val availableCallables = shorteningContext.findPropertiesInScopes(scopes, propertySymbol.name)
// if explicit receiver is a property access or a function call, we cannot shorten it
if (firPropertyAccess.explicitReceiver !is FirResolvedQualifier) return
if (availableCallables.isNotEmpty() && shortenIfAlreadyImported(firPropertyAccess, callableSymbol, referenceExpression)) {
if (availableCallables.isNotEmpty() && shortenIfAlreadyImported(firPropertyAccess, propertySymbol, qualifiedProperty)) {
addElementToShorten(ShortenQualifier(qualifiedProperty))
return
}
if (option == ShortenOption.SHORTEN_IF_ALREADY_IMPORTED) return
processCallableQualifiedAccess(
callableSymbol,
propertySymbol,
option,
qualifiedProperty,
availableCallables,
)
}
private fun KtDotQualifiedExpression.getCorrespondingPropertyAccessExpression(): FirPropertyAccessExpression? {
val accessExpression = when (val fir = getOrBuildFir(firResolveSession)) {
is FirVariableAssignment -> fir.unwrapLValue()
else -> fir
}
return accessExpression as? FirPropertyAccessExpression
}
private val FirPropertyAccessExpression.referencedSymbol: FirVariableSymbol<*>?
get() = (calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirVariableSymbol<*>
private fun processFunctionCall(functionCall: FirFunctionCall) {
if (!canBePossibleToDropReceiver(functionCall)) return