KT-62695 [AA] Add ResolveResult data class to KDocReferenceResolver

It's a part of implementation; it will be required to properly navigate
from resolved extension function to its receiver type, since receiver
type cannot be properly inferred from the function symbol itself
This commit is contained in:
Roman Golyshev
2024-01-22 18:34:34 +01:00
committed by Space Team
parent f9d4a35d80
commit 42753c461f
@@ -26,6 +26,9 @@ import org.jetbrains.kotlin.analysis.utils.printer.parentOfType
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
internal object KDocReferenceResolver { internal object KDocReferenceResolver {
private data class ResolveResult(val symbol: KtSymbol)
private fun KtSymbol.toResolveResult(): ResolveResult = ResolveResult(this)
/** /**
* Resolves the [selectedFqName] of KDoc * Resolves the [selectedFqName] of KDoc
@@ -47,7 +50,7 @@ internal object KDocReferenceResolver {
context(KtAnalysisSession) context(KtAnalysisSession)
internal fun resolveKdocFqName(selectedFqName: FqName, fullFqName: FqName, contextElement: KtElement): Collection<KtSymbol> { internal fun resolveKdocFqName(selectedFqName: FqName, fullFqName: FqName, contextElement: KtElement): Collection<KtSymbol> {
val fullSymbolsResolved = resolveKdocFqName(fullFqName, contextElement) val fullSymbolsResolved = resolveKdocFqName(fullFqName, contextElement)
if (selectedFqName == fullFqName) return fullSymbolsResolved if (selectedFqName == fullFqName) return fullSymbolsResolved.map { it.symbol }
if (fullSymbolsResolved.isEmpty()) { if (fullSymbolsResolved.isEmpty()) {
val parent = fullFqName.parent() val parent = fullFqName.parent()
return resolveKdocFqName(selectedFqName = selectedFqName, fullFqName = parent, contextElement = contextElement) return resolveKdocFqName(selectedFqName = selectedFqName, fullFqName = parent, contextElement = contextElement)
@@ -56,7 +59,7 @@ internal object KDocReferenceResolver {
check(goBackSteps > 0) { check(goBackSteps > 0) {
"Selected FqName ($selectedFqName) should be smaller than the whole FqName ($fullFqName)" "Selected FqName ($selectedFqName) should be smaller than the whole FqName ($fullFqName)"
} }
return fullSymbolsResolved.mapNotNullTo(mutableSetOf()) { findParentSymbol(it, goBackSteps, selectedFqName) } return fullSymbolsResolved.mapNotNullTo(mutableSetOf()) { findParentSymbol(it.symbol, goBackSteps, selectedFqName) }
} }
@@ -83,31 +86,31 @@ internal object KDocReferenceResolver {
} }
context(KtAnalysisSession) context(KtAnalysisSession)
private fun resolveKdocFqName(fqName: FqName, contextElement: KtElement): Collection<KtSymbol> { private fun resolveKdocFqName(fqName: FqName, contextElement: KtElement): Collection<ResolveResult> {
getExtensionReceiverSymbolByThisQualifier(fqName, contextElement).ifNotEmpty { return this } getExtensionReceiverSymbolByThisQualifier(fqName, contextElement).ifNotEmpty { return this }
getSymbolsFromExistingScopes(fqName, contextElement).ifNotEmpty { return this } getSymbolsFromExistingScopes(fqName, contextElement).ifNotEmpty { return this }
getNonImportedSymbolsByFullyQualifiedName(fqName).ifNotEmpty { return this } getNonImportedSymbolsByFullyQualifiedName(fqName).map { it.toResolveResult() }.ifNotEmpty { return this }
AdditionalKDocResolutionProvider.resolveKdocFqName(fqName, contextElement).ifNotEmpty { return this } AdditionalKDocResolutionProvider.resolveKdocFqName(fqName, contextElement).map { it.toResolveResult() }.ifNotEmpty { return this }
return emptyList() return emptyList()
} }
context(KtAnalysisSession) context(KtAnalysisSession)
fun getExtensionReceiverSymbolByThisQualifier(fqName: FqName, contextElement: KtElement): Collection<KtSymbol> { private fun getExtensionReceiverSymbolByThisQualifier(fqName: FqName, contextElement: KtElement): Collection<ResolveResult> {
val owner = contextElement.parentOfType<KtDeclaration>() ?: return emptyList() val owner = contextElement.parentOfType<KtDeclaration>() ?: return emptyList()
if (fqName.pathSegments().singleOrNull()?.asString() == "this") { if (fqName.pathSegments().singleOrNull()?.asString() == "this") {
if (owner is KtCallableDeclaration && owner.receiverTypeReference != null) { if (owner is KtCallableDeclaration && owner.receiverTypeReference != null) {
val symbol = owner.getSymbol() as? KtCallableSymbol ?: return emptyList() val symbol = owner.getSymbol() as? KtCallableSymbol ?: return emptyList()
return listOfNotNull(symbol.receiverParameter) return listOfNotNull(symbol.receiverParameter).map { it.toResolveResult() }
} }
} }
return emptyList() return emptyList()
} }
context(KtAnalysisSession) context(KtAnalysisSession)
private fun getSymbolsFromExistingScopes(fqName: FqName, contextElement: KtElement): Collection<KtSymbol> = private fun getSymbolsFromExistingScopes(fqName: FqName, contextElement: KtElement): Collection<ResolveResult> =
buildList { buildList {
addAll(getSymbolsFromScopes(fqName, contextElement)) getSymbolsFromScopes(fqName, contextElement).mapTo(this) { it.toResolveResult() }
addIfNotNull(getPackageSymbolIfPackageExists(fqName)) addIfNotNull(getPackageSymbolIfPackageExists(fqName)?.toResolveResult())
} }
context(KtAnalysisSession) context(KtAnalysisSession)